URI: 
       * Find binaries in PATH when specified in path '*' * Check return value of lstat - sup - small tool for privilege escalation
  HTML git clone git://bitreich.org/sup git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/sup
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
   DIR LICENSE
       ---
   DIR commit 836d0723d883384c1ea8e1b4c3fd23eced9c8043
   DIR parent 8078fe60673809c9ce32dd85613e9f96d7278742
  HTML 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:
         M config.def.h                        |       3 ++-
         M sup.c                               |      47 ++++++++++++++++++++++++-------
       
       2 files changed, 39 insertions(+), 11 deletions(-)
       ---
   DIR 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 },
        };
   DIR 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));
                        }
                }