sup

simple user privilege escalation
git clone git://git.suckless.org/sup
Log | Files | Refs

commit 989bc1c744d8fe03a58692410a6d68ad00a872c8
Author: pancake@dazo <unknown>
Date:   Mon, 14 Dec 2009 01:02:07 +0100

* Initial import of 'sup' into mercurial
Diffstat:
Makefile | 31+++++++++++++++++++++++++++++++
TODO | 1+
config.def.h | 18++++++++++++++++++
sup.1 | 23+++++++++++++++++++++++
sup.c | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 145 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -0,0 +1,31 @@ +CC?=gcc +DESTDIR?= +PREFIX?=/usr +VERSION=0.1 +USER=root +GROUP=root + +all: config.h sup + +config.h: + cp config.def.h config.h + +sup.o: config.h sup.c + ${CC} -c sup.c + +sup: sup.o + ${CC} sup.o -o sup + +clean: + rm -f sup.o sup + +mrproper: clean + rm -f config.h + +install: + mkdir -p ${DESTDIR}${PREFIX}/bin + cp sup ${DESTDIR}${PREFIX}/bin + chown ${USER}:${GROUP} ${DESTDIR}/${PREFIX}/bin/sup + chmod 4111 ${DESTDIR}${PREFIX}/bin/sup + sed s,VERSION,${VERSION}, sup.1 \ + > ${DESTDIR}${PREFIX}/share/man/man1/sup.1 diff --git a/TODO b/TODO @@ -0,0 +1 @@ +* Enforce with checksums (sha1?) diff --git a/config.def.h b/config.def.h @@ -0,0 +1,18 @@ +#define USER 1000 +#define GROUP -1 + +#define SETUID 0 +#define SETGID 0 + +#define CHROOT "/" + +#define ENFORCE 1 + +static struct rule_t rules[] = { + { USER, GROUP, "whoami", "/usr/bin/whoami" }, + { USER, GROUP, "ifconfig", "/sbin/ifconfig" }, + { USER, GROUP, "ls", "/bin/ls" }, + { USER, GROUP, "wifi", "/root/wifi.sh" }, + { USER, GROUP, "", ""}, // allow to run any program + { 0 }, +}; diff --git a/sup.1 b/sup.1 @@ -0,0 +1,23 @@ +.TH SUP 1 sup\-VERSION +.SH NAME +sup - scale user priviledges +.SH SYNOPSIS +.B sup +.RB [ \-hlv ] +.SH DESCRIPTION +sup is a minimal priviledge scalation utility that allow normal +users to run other programs as different user and group. +.P +The configuration is done in config.h at compile time. +.SH OPTIONS +.TP +.B \-h +print help message +.TP +.B \-l +list command whitelist +.TP +.B \-v +prints version information +.SH AUTHOR +pancake <nopcode.org> diff --git a/sup.c b/sup.c @@ -0,0 +1,72 @@ +/* pancake <nopcode.org> -- Copyleft 2009 */ + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <sys/stat.h> + +#define HELP "sup [-hlv] [cmd ..]" +#define VERSION "sup 0.1 pancake <nopcode.org> copyleft 2009" + +struct rule_t { + int uid; + int gid; + const char *cmd; + const char *path; +}; + +#include "config.h" + +static int die(int ret, const char *str) { + fprintf (stderr, "%s\n", str); + return ret; +} + +int main(int argc, char **argv) { + char *cmd; + int i, uid, gid, ret; + + if (argc < 2 || !strcmp (argv[1], "-h")) + return die (1, HELP); + + if (!strcmp (argv[1], "-v")) + return die (1, VERSION); + + if (!strcmp (argv[1], "-l")) { + for (i = 0; rules[i].cmd != NULL; i++) + printf ("%d %d %10s %s\n", rules[i].uid, rules[i].gid, + rules[i].cmd, rules[i].path); + return 0; + } + + uid = getuid (); + gid = getgid (); + + for (i = 0; rules[i].cmd != NULL; i++) { + if (!rules[i].cmd[0] || !strcmp (argv[1], rules[i].cmd)) { +#if ENFORCE + struct stat st; + lstat (rules[i].path, &st); + if (st.st_mode & 0222) + return die (1, "Cannot run writable binaries."); +#endif + if (uid != SETUID && rules[i].uid != -1 && rules[i].uid != uid) + return die (1, "User does not match"); + + if (gid != SETGID && rules[i].gid != -1 && rules[i].gid != gid) + return die (1, "Group id does not match"); + + if (setuid (SETUID) == -1 || setgid (SETGID) == -1 || + seteuid (SETUID) == -1 || setegid (SETGID) == -1) + return die (1, strerror (errno)); +#ifdef CHROOT + if (chroot (CHROOT) == -1) + return die (1, strerror (errno)); +#endif + ret = execv (rules[i].path? rules[i].path:argv[1], argv+1); + return die (ret, strerror (errno)); + } + } + + return die (1, "Sorry"); +}