Last active
December 19, 2018 14:46
-
-
Save AGhost-7/91788e4545cd9e20f69b356ca5ffec46 to your computer and use it in GitHub Desktop.
Strip supplementary groups from new process (requires setuid)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Removes supplementary groups (e.g., sudo and docker) of the current process | |
* then uses `exec` to make a different program take over the process. This | |
* allows me to run certain programs (such as npm) with lowered permissions. | |
* | |
* Note that this requires the container option `--cap-add SETGID` to work. | |
* It will fail silently and simply exec the program otherwise. | |
* | |
* For example: | |
* alias npm='unpriviledged npm' | |
*/ | |
#include <grp.h> | |
#include <unistd.h> | |
#include <errno.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/types.h> | |
/* | |
* Returns the new groups that the process should be given. | |
*/ | |
//int set_new_groups() | |
//{ | |
// //size_t gids_mem = sizeof(gid_t) * size; | |
// //gid_t * gids = malloc(gids_mem); | |
// //memset(gids, 0, gids_mem); | |
// gid_t gids[100]; | |
// gid_t groups[100]; | |
// int gids_size = getgroups(100, gids); | |
// if (gids_size == -1) { | |
// printf("Failed to retrieve groups (%d)\n", errno); | |
// return -1; | |
// } | |
// | |
// int group_size = 0; | |
// struct group *gr; | |
// for(int i = 0; i < gids_size; i++) { | |
// gr = getgrgid(groups[i]); | |
// if (gr == NULL) { | |
// printf("Group NULL: %d\n", groups[i]); | |
// } else { | |
// printf("Group name: %s\n", gr->gr_name); | |
// } | |
// if (gr != NULL | |
// && !strcmp(gr->gr_name, "docker") | |
// && !strcmp(gr->gr_name, "sudo")) { | |
// if(group_size + 1 > 100) { | |
// printf("Too many groups\n"); | |
// return -1; | |
// } | |
// //printf("found group %d, index: %d\n", groups[i], i); | |
// groups[group_size] = groups[i]; | |
// group_size++; | |
// } | |
// } | |
// | |
// gid_t setting [] = { | |
// }; | |
// | |
// if (setgroups(0, setting) == -1) { | |
// printf("Nop\n"); | |
// // EPERM: Skip if I don't have permission to change groups, otherwise | |
// // it is an unexpected error. | |
// if(errno != 1) { | |
// printf("Error setting process groups (%d)\n", errno); | |
// return 1; | |
// } | |
// } | |
// printf("group size %d\n", group_size); | |
// return 0; | |
//} | |
int exec_argv(int argc, char *argv[]) | |
{ | |
if (argc == 1) { | |
printf("No command specified\n"); | |
return -1; | |
} | |
char * path = argv[1]; | |
char ** args = malloc(sizeof(char*) * (argc)); | |
for(int i = 1; i < argc; i++) { | |
args[i - 1] = argv[i]; | |
} | |
args[argc - 1] = NULL; | |
if (execvp(path, args) == -1) { | |
free(args); | |
printf("Error exec'ing (%d)\n", errno); | |
return -1; | |
} | |
return 0; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
//printf("egid: %d, gid: %d\n", getegid(), getgid()); | |
//printf("uid: %d\n", getuid()); | |
errno = 0; | |
gid_t no_groups[] = {}; | |
if (setgroups(0, no_groups) == -1) { | |
printf("Error changing supplementary groups (%d)\n", errno); | |
return 1; | |
} | |
// 65534: nogroup | |
if (setgid(getgid()) == -1) { | |
printf("Error changing guid (%d)\n", errno); | |
return 1; | |
} | |
printf("gid: %d, egid: %d\n", getgid(), getegid()); | |
if (setuid(getuid()) == -1) { | |
printf("Error changing uid (%d)\n", errno); | |
return 1; | |
} | |
// reset the session to prevent tty hijacking. | |
//if (setsid() == -1) { | |
// printf("Failed to reset session (%d)\n", errno); | |
// return 1; | |
//} | |
if (exec_argv(argc, argv) == -1) { | |
return 1; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment