itRewrite C code and add SHA256 support. - sup - small tool for privilege escalation Err parazyd.org 70 hgit clone https://git.parazyd.org/sup URL:https://git.parazyd.org/sup parazyd.org 70 1Log /git/sup/log.gph parazyd.org 70 1Files /git/sup/files.gph parazyd.org 70 1Refs /git/sup/refs.gph parazyd.org 70 1README /git/sup/file/README.gph parazyd.org 70 1LICENSE /git/sup/file/LICENSE.gph parazyd.org 70 i--- Err parazyd.org 70 1commit cec5f362b273867f23126ccb7a756905c640c856 /git/sup/commit/cec5f362b273867f23126ccb7a756905c640c856.gph parazyd.org 70 1parent 96b227c7bf3acc15c0de695b074f2b32fcabe21e /git/sup/commit/96b227c7bf3acc15c0de695b074f2b32fcabe21e.gph parazyd.org 70 hAuthor: parazyd URL:mailto:parazyd@dyne.org parazyd.org 70 iDate: Tue, 2 Jul 2019 13:00:38 +0200 Err parazyd.org 70 i Err parazyd.org 70 iRewrite C code and add SHA256 support. Err parazyd.org 70 i Err parazyd.org 70 iDiffstat: Err parazyd.org 70 i M config.def.h | 33 +++++++++++++++++++------------ Err parazyd.org 70 i M sup.c | 158 ++++++++++++++++--------------- Err parazyd.org 70 i Err parazyd.org 70 i2 files changed, 103 insertions(+), 88 deletions(-) Err parazyd.org 70 i--- Err parazyd.org 70 1diff --git a/config.def.h b/config.def.h /git/sup/file/config.def.h.gph parazyd.org 70 it@@ -1,20 +1,27 @@ Err parazyd.org 70 i-#define USER 1000 Err parazyd.org 70 i-#define GROUP -1 Err parazyd.org 70 i+/* See LICENSE file for copyright and license details. */ Err parazyd.org 70 i Err parazyd.org 70 i+/* User and group to run as */ Err parazyd.org 70 i #define SETUID 0 Err parazyd.org 70 i #define SETGID 0 Err parazyd.org 70 i Err parazyd.org 70 i-#define CHROOT "" Err parazyd.org 70 i-#define CHRDIR "" Err parazyd.org 70 i+/* sup authorizations Err parazyd.org 70 i+ * Err parazyd.org 70 i+ * The format is as follows: Err parazyd.org 70 i+ * - UID allowed to run the command (-1 means anyone) Err parazyd.org 70 i+ * - Alias/command used to call the executable Err parazyd.org 70 i+ * - Path to the executable to run Err parazyd.org 70 i+ * - SHA256 checksum of the executable Err parazyd.org 70 i+ */ Err parazyd.org 70 i+static struct rule_t rules[] = { Err parazyd.org 70 i+ { 1000, "ls", "/bin/ls", Err parazyd.org 70 i+ "87e8fd7d813c135875aca43a4da43d3ced41d325ed2931906444471b4e93e017" }, Err parazyd.org 70 i Err parazyd.org 70 i-#define ENFORCE 1 Err parazyd.org 70 i+ { -1, "grep", "/bin/grep", Err parazyd.org 70 i+ "fedeb344d1be24f4a340591cd25ed81f7e46ea12772f563c9c9f43773028e23a" }, Err parazyd.org 70 i Err parazyd.org 70 i-static struct rule_t rules[] = { Err parazyd.org 70 i- { USER, GROUP, "whoami", "/usr/bin/whoami" }, Err parazyd.org 70 i- { USER, GROUP, "ifconfig", "/sbin/ifconfig" }, Err parazyd.org 70 i- { USER, GROUP, "ls", "/bin/ls" }, Err parazyd.org 70 i- { USER, GROUP, "wifi", "/root/wifi.sh" }, Err parazyd.org 70 i- { USER, GROUP, "cp", "*"}, // allow to run this program in PATH Err parazyd.org 70 i- { USER, GROUP, "*", "*"}, // allow to run any program in PATH Err parazyd.org 70 i- { 0 }, Err parazyd.org 70 i+ { 1000, "tar", "/bin/tar", Err parazyd.org 70 i+ "fedeb344d1be24f4a340591cd25ed81f7e46ea12772f563c9c9f43773028e23a" }, Err parazyd.org 70 i+ Err parazyd.org 70 i+ { 1001, "test", "./a.out", Err parazyd.org 70 i+ "254260b676a44f1529f7c855f0126a57a3fbd7ec8a74de08835f08e8e6ed21be" }, Err parazyd.org 70 i }; Err parazyd.org 70 1diff --git a/sup.c b/sup.c /git/sup/file/sup.c.gph parazyd.org 70 it@@ -1,103 +1,111 @@ Err parazyd.org 70 i-/* pancake -- Copyleft 2009-2011 */ Err parazyd.org 70 i+/* See LICENSE file for copyright and license details. */ Err parazyd.org 70 i Err parazyd.org 70 i-#include Err parazyd.org 70 i-#include Err parazyd.org 70 i #include Err parazyd.org 70 i-#include Err parazyd.org 70 i #include Err parazyd.org 70 i+#include Err parazyd.org 70 i #include Err parazyd.org 70 i+#include Err parazyd.org 70 i+ Err parazyd.org 70 i+#include "arg.h" Err parazyd.org 70 i+#include "sha256.h" Err parazyd.org 70 i Err parazyd.org 70 i-#define HELP "sup [-hlv] [cmd ..]" Err parazyd.org 70 i-#define VERSION "sup 0.1 pancake copyleft 2011" Err parazyd.org 70 i+#define nelem(x) (sizeof (x) / sizeof *(x)) Err parazyd.org 70 i Err parazyd.org 70 i struct rule_t { Err parazyd.org 70 i- int uid; Err parazyd.org 70 i- int gid; Err parazyd.org 70 i+ const int uid; Err parazyd.org 70 i const char *cmd; Err parazyd.org 70 i const char *path; Err parazyd.org 70 i+ const char *hash; Err parazyd.org 70 i }; Err parazyd.org 70 i Err parazyd.org 70 i #include "config.h" Err parazyd.org 70 i Err parazyd.org 70 i-static int die(int ret, const char *org, const char *str) { Err parazyd.org 70 i- fprintf (stderr, "%s%s%s\n", org?org:"", org?": ":"", str); Err parazyd.org 70 i- return ret; Err parazyd.org 70 i+char *argv0; Err parazyd.org 70 i+ Err parazyd.org 70 i+void die(char *msg) { Err parazyd.org 70 i+ fprintf(stderr, "%s\n", msg); Err parazyd.org 70 i+ exit(1); Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i-static char *getpath(const char *str) { Err parazyd.org 70 i- struct stat st; Err parazyd.org 70 i- static char file[4096]; Err parazyd.org 70 i- char *p, *path = getenv ("PATH"); Err parazyd.org 70 i- if (path) Err parazyd.org 70 i- for (p = path; *p; p++) { Err parazyd.org 70 i- if (*p==':' && (p>path&&*(p-1)!='\\')) { Err parazyd.org 70 i- *p = 0; Err parazyd.org 70 i- snprintf (file, sizeof (file)-1, "%s/%s", path, str); Err parazyd.org 70 i- if (!lstat (file, &st)) Err parazyd.org 70 i- return file; Err parazyd.org 70 i- *p = ':'; Err parazyd.org 70 i- path = p+1; Err parazyd.org 70 i- } Err parazyd.org 70 i+#define CHUNK 1048576 /* 1MiB */ Err parazyd.org 70 i+static uint32 getsha(const char *path, unsigned char *dest) { Err parazyd.org 70 i+ static sha256_context sha; Err parazyd.org 70 i+ Err parazyd.org 70 i+ unsigned char buf[CHUNK]; Err parazyd.org 70 i+ uint32 len, tot = 0; Err parazyd.org 70 i+ FILE *fd; Err parazyd.org 70 i+ Err parazyd.org 70 i+ fd = fopen(path, "r"); Err parazyd.org 70 i+ if (!fd) Err parazyd.org 70 i+ die("Can not read binary file."); Err parazyd.org 70 i+ Err parazyd.org 70 i+ sha256_starts(&sha); Err parazyd.org 70 i+ Err parazyd.org 70 i+ while ((len = fread(buf, 1, CHUNK, fd))) { Err parazyd.org 70 i+ sha256_update(&sha, buf, len); Err parazyd.org 70 i+ tot += len; Err parazyd.org 70 i } Err parazyd.org 70 i- return NULL; Err parazyd.org 70 i+ fclose(fd); Err parazyd.org 70 i+ Err parazyd.org 70 i+ sha256_finish(&sha, dest); Err parazyd.org 70 i+ return tot; Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i-int main(int argc, char **argv) { Err parazyd.org 70 i- const char *cmd; Err parazyd.org 70 i- int i, uid, gid, ret; Err parazyd.org 70 i+int main(int argc, char *argv[]) { Err parazyd.org 70 i+ unsigned int c, i, lflag = 0; Err parazyd.org 70 i+ unsigned char digest[32]; Err parazyd.org 70 i+ char output[65]; Err parazyd.org 70 i+ struct stat st; Err parazyd.org 70 i Err parazyd.org 70 i- if (argc < 2 || !strcmp (argv[1], "-h")) Err parazyd.org 70 i- return die (1, NULL, HELP); Err parazyd.org 70 i+ ARGBEGIN { Err parazyd.org 70 i+ case 'l': Err parazyd.org 70 i+ lflag = 1; Err parazyd.org 70 i+ break; Err parazyd.org 70 i+ default: Err parazyd.org 70 i+ die("Usage: sup [-l] command [ args ... ]"); Err parazyd.org 70 i+ } ARGEND; Err parazyd.org 70 i Err parazyd.org 70 i- if (!strcmp (argv[1], "-v")) Err parazyd.org 70 i- return die (1, NULL, VERSION); Err parazyd.org 70 i+ if (lflag) { Err parazyd.org 70 i+ printf("List of compiled authorizations:\n"); Err parazyd.org 70 i+ for (i = 0; i < nelem(rules); i++) Err parazyd.org 70 i+ printf("\nuser: %d\ncmd: %s\nbinary: %s\nsha256: %s\n", Err parazyd.org 70 i+ rules[i].uid, rules[i].cmd, rules[i].path, rules[i].hash); Err parazyd.org 70 i Err parazyd.org 70 i- if (!strcmp (argv[1], "-l")) { Err parazyd.org 70 i- for (i = 0; rules[i].cmd != NULL; i++) Err parazyd.org 70 i- printf ("%d %d %10s %s\n", rules[i].uid, rules[i].gid, Err parazyd.org 70 i- rules[i].cmd, rules[i].path); Err parazyd.org 70 i return 0; Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i- uid = getuid (); Err parazyd.org 70 i- gid = getgid (); Err parazyd.org 70 i- Err parazyd.org 70 i- for (i = 0; rules[i].cmd != NULL; i++) { Err parazyd.org 70 i- if (*rules[i].cmd=='*' || !strcmp (argv[1], rules[i].cmd)) { Err parazyd.org 70 i-#if ENFORCE Err parazyd.org 70 i- struct stat st; Err parazyd.org 70 i- if (*rules[i].path=='*') { Err parazyd.org 70 i- if (*argv[1]=='.' || *argv[1]=='/') Err parazyd.org 70 i- cmd = argv[1]; Err parazyd.org 70 i- else if (!(cmd = getpath (argv[1]))) Err parazyd.org 70 i- return die (1, "execv", "cannot find program"); Err parazyd.org 70 i- } else cmd = rules[i].path; Err parazyd.org 70 i- if (lstat (cmd, &st) == -1) Err parazyd.org 70 i- return die (1, "lstat", "cannot stat program"); Err parazyd.org 70 i- if (st.st_mode & 0222) Err parazyd.org 70 i- return die (1, "stat", "cannot run writable binaries."); Err parazyd.org 70 i-#endif Err parazyd.org 70 i- if (uid != SETUID && rules[i].uid != -1 && rules[i].uid != uid) Err parazyd.org 70 i- return die (1, "urule", "user does not match"); Err parazyd.org 70 i- Err parazyd.org 70 i- if (gid != SETGID && rules[i].gid != -1 && rules[i].gid != gid) Err parazyd.org 70 i- return die (1, "grule", "group id does not match"); Err parazyd.org 70 i- Err parazyd.org 70 i- if (setuid (SETUID) == -1 || setgid (SETGID) == -1 || Err parazyd.org 70 i- seteuid (SETUID) == -1 || setegid (SETGID) == -1) Err parazyd.org 70 i- return die (1, "set[e][ug]id", strerror (errno)); Err parazyd.org 70 i-#ifdef CHROOT Err parazyd.org 70 i- if (*CHROOT) Err parazyd.org 70 i- if (chdir (CHROOT) == -1 || chroot (".") == -1) Err parazyd.org 70 i- return die (1, "chroot", strerror (errno)); Err parazyd.org 70 i- if (*CHRDIR) Err parazyd.org 70 i- if (chdir (CHRDIR) == -1) Err parazyd.org 70 i- return die (1, "chdir", strerror (errno)); Err parazyd.org 70 i-#endif Err parazyd.org 70 i- ret = execv (cmd, argv+1); Err parazyd.org 70 i- return die (ret, "execv", strerror (errno)); Err parazyd.org 70 i+ if (argc < 1) Err parazyd.org 70 i+ die("Usage: sup [-l] command [ args ... ]"); Err parazyd.org 70 i+ Err parazyd.org 70 i+ for (i = 0; i < nelem(rules); i++) { Err parazyd.org 70 i+ if (!strcmp(argv[0], rules[i].cmd)) { Err parazyd.org 70 i+ Err parazyd.org 70 i+ if (rules[i].uid != getuid() && rules[i].uid != -1) Err parazyd.org 70 i+ die("Unauthorized user."); Err parazyd.org 70 i+ Err parazyd.org 70 i+ if (stat(rules[i].path, &st) == -1) Err parazyd.org 70 i+ die("Can not stat program."); Err parazyd.org 70 i+ Err parazyd.org 70 i+ if (st.st_mode & 0022) Err parazyd.org 70 i+ die("Can not run binaries others can write."); Err parazyd.org 70 i+ Err parazyd.org 70 i+ if (getsha(rules[i].path, digest) != st.st_size) Err parazyd.org 70 i+ die("Binary file differs from size read."); Err parazyd.org 70 i+ Err parazyd.org 70 i+ for (c = 0; c < 32; c++) Err parazyd.org 70 i+ sprintf(output + (c*2), "%02x", digest[c]); Err parazyd.org 70 i+ output[64] = '\0'; Err parazyd.org 70 i+ Err parazyd.org 70 i+ if (strncmp(rules[i].hash, output, 64)) Err parazyd.org 70 i+ die("Checksums do not match."); Err parazyd.org 70 i+ Err parazyd.org 70 i+ if (setgid(SETGID) < 0) die("setgid failed"); Err parazyd.org 70 i+ if (setuid(SETUID) < 0) die("setuid failed"); Err parazyd.org 70 i+ Err parazyd.org 70 i+ if (execv(rules[i].path, argv) < 0) Err parazyd.org 70 i+ die("execv failed."); Err parazyd.org 70 i } Err parazyd.org 70 i } Err parazyd.org 70 i Err parazyd.org 70 i- return die (1, NULL, "Sorry"); Err parazyd.org 70 i+ die("Unauthorized command."); Err parazyd.org 70 i } Err parazyd.org 70 .