Skip to content

Instantly share code, notes, and snippets.

@AGhost-7
Last active December 19, 2018 14:46
Show Gist options
  • Save AGhost-7/91788e4545cd9e20f69b356ca5ffec46 to your computer and use it in GitHub Desktop.
Save AGhost-7/91788e4545cd9e20f69b356ca5ffec46 to your computer and use it in GitHub Desktop.
Strip supplementary groups from new process (requires setuid)
/*
* 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