sup

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

commit 836d0723d883384c1ea8e1b4c3fd23eced9c8043
parent 8078fe60673809c9ce32dd85613e9f96d7278742
Author: pancake <unknown>
Date:   Thu, 31 Mar 2011 20:56:00 +0200

* Find binaries in PATH when specified in path '*'
* Check return value of lstat
Diffstat:
config.def.h | 3++-
sup.c | 47+++++++++++++++++++++++++++++++++++++----------
2 files changed, 39 insertions(+), 11 deletions(-)

diff --git a/config.def.h b/config.def.h @@ -14,6 +14,7 @@ static struct rule_t rules[] = { { USER, GROUP, "ifconfig", "/sbin/ifconfig" }, { USER, GROUP, "ls", "/bin/ls" }, { USER, GROUP, "wifi", "/root/wifi.sh" }, - { USER, GROUP, "", ""}, // allow to run any program + { USER, GROUP, "cp", "*"}, // allow to run this program in PATH + { USER, GROUP, "*", "*"}, // allow to run any program in PATH { 0 }, }; diff --git a/sup.c b/sup.c @@ -1,13 +1,14 @@ -/* pancake <nopcode.org> -- Copyleft 2009 */ +/* pancake <nopcode.org> -- Copyleft 2009-2011 */ #include <errno.h> -#include <stdio.h> #include <unistd.h> +#include <stdio.h> #include <string.h> +#include <stdlib.h> #include <sys/stat.h> #define HELP "sup [-hlv] [cmd ..]" -#define VERSION "sup 0.1 pancake <nopcode.org> copyleft 2009" +#define VERSION "sup 0.1 pancake <nopcode.org> copyleft 2011" struct rule_t { int uid; @@ -19,11 +20,30 @@ struct rule_t { #include "config.h" static int die(int ret, const char *org, const char *str) { - fprintf (stderr, "%s%s%s\n", org, org?": ":"", str); + fprintf (stderr, "%s%s%s\n", org?org:"", org?": ":"", str); return ret; } +static char *getpath(const char *str) { + struct stat st; + static char file[4096]; + char *p, *path = getenv ("PATH"); + if (path) + for (p = path; *p; p++) { + if (*p==':' && (p>path&&*(p-1)!='\\')) { + *p = 0; + snprintf (file, sizeof (file)-1, "%s/%s", path, str); + if (!lstat (file, &st)) + return file; + *p = ':'; + path = p+1; + } + } + return NULL; +} + int main(int argc, char **argv) { + const char *cmd; int i, uid, gid, ret; if (argc < 2 || !strcmp (argv[1], "-h")) @@ -43,18 +63,25 @@ int main(int argc, char **argv) { gid = getgid (); for (i = 0; rules[i].cmd != NULL; i++) { - if (!rules[i].cmd[0] || !strcmp (argv[1], rules[i].cmd)) { + if (*rules[i].cmd=='*' || !strcmp (argv[1], rules[i].cmd)) { #if ENFORCE struct stat st; - lstat (rules[i].path, &st); + if (*rules[i].path=='*') { + if (*argv[1]=='.' || *argv[1]=='/') + cmd = argv[1]; + else if (!(cmd = getpath (argv[1]))) + return die (1, "execv", "cannot find program"); + } else cmd = rules[i].path; + if (lstat (cmd, &st) == -1) + return die (1, "lstat", "cannot stat program"); if (st.st_mode & 0222) - return die (1, "stat", "Cannot run writable binaries."); + return die (1, "stat", "cannot run writable binaries."); #endif if (uid != SETUID && rules[i].uid != -1 && rules[i].uid != uid) - return die (1, "urule", "User does not match"); + return die (1, "urule", "user does not match"); if (gid != SETGID && rules[i].gid != -1 && rules[i].gid != gid) - return die (1, "grule", "Group id does not match"); + return die (1, "grule", "group id does not match"); if (setuid (SETUID) == -1 || setgid (SETGID) == -1 || seteuid (SETUID) == -1 || setegid (SETGID) == -1) @@ -67,7 +94,7 @@ int main(int argc, char **argv) { if (chdir (CHRDIR) == -1) return die (1, "chdir", strerror (errno)); #endif - ret = execv (*rules[i].path? rules[i].path:argv[1], argv+1); + ret = execv (cmd, argv+1); return die (ret, "execv", strerror (errno)); } }