diff options
author | Andrew G. Morgan <morgan@kernel.org> | 2022-10-09 14:41:45 -0700 |
---|---|---|
committer | Andrew G. Morgan <morgan@kernel.org> | 2022-10-09 14:41:45 -0700 |
commit | 911da84bf4e1613567d4ef57e70c85326161ccad (patch) | |
tree | cca233a084a9ab76a8e3bcc404b94d73949ebab1 | |
parent | b643699aa65388dd248e67e18004cad416bc4a7c (diff) | |
download | libcap-911da84bf4e1613567d4ef57e70c85326161ccad.tar.gz |
Add some exploit demonstration code to capso.so
This exploit code requires a make variable to activate, but
is used in the companion article discussing this code to compare
and contrast setuid-root to file capable privilege. Tl;dr don't
use setuid-root for shared libraries in this way!
Follow along here:
https://sites.google.com/site/fullycapable/capable-shared-objects
Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
-rw-r--r-- | contrib/capso/.gitignore | 2 | ||||
-rw-r--r-- | contrib/capso/capso.c | 83 |
2 files changed, 78 insertions, 7 deletions
diff --git a/contrib/capso/.gitignore b/contrib/capso/.gitignore new file mode 100644 index 0000000..222d35d --- /dev/null +++ b/contrib/capso/.gitignore @@ -0,0 +1,2 @@ +capso.so +bind diff --git a/contrib/capso/capso.c b/contrib/capso/capso.c index 2a357c0..7ca3427 100644 --- a/contrib/capso/capso.c +++ b/contrib/capso/capso.c @@ -26,6 +26,73 @@ #include "capso.h" +extern char **environ; + +/* + * fake_exploit is some dedicated code to simulate a shell escape type + * exploit. This is obviously not something serious to include in code + * that has actually been audited for security, but we use it to + * demonstrate an aspect of file capabilities vs. setuid root for + * granting privilege. + */ +static void fake_exploit(void) { +#ifdef ALLOW_EXPLOIT + const char *exploit = getenv("TRIGGER_EXPLOIT"); + if (exploit == NULL) { + return; + } + + switch (*exploit) { + case '^': + case '%': + exploit++; + cap_value_t caps = CAP_NET_BIND_SERVICE; + cap_t c = cap_get_proc(); + cap_set_flag(c, CAP_INHERITABLE, 1, &caps, CAP_SET); + if (cap_set_proc(c)) { + perror("Failed to raise inheritable capability"); + exit(1); + } + if (*(exploit-1) == '%') { + break; + } + cap_free(c); + if (cap_set_ambient(caps, CAP_SET) != 0) { + perror("Unable to raise ambient capability"); + exit(1); + } + break; + } + + char *ts = strdup(exploit); + if (ts == NULL) { + perror("Failed to duplicate exploit string"); + exit(1); + } + + int i, j, n = 1; + for (i = 0; ts[i]; i++) { + switch (ts[i]) { + case ' ': + case '\t': + n++; + ts[i] = '\0'; + } + } + char **argv = calloc(n, sizeof(char *)); + for (i = 0, j = 0; j < n; j++) { + char *s = ts+i; + argv[j] = s; + i += 1 + strlen(s); + printf("execv argv[%d] = \"%s\"\n", j, s); + } + + execv(argv[0], argv); + perror("Execv failed"); + exit(1); +#endif /* def ALLOW_EXPLOIT */ +} + /* * where_am_i determines the full path for the shared libary that * contains this function. It allocates the path in strdup()d memory @@ -160,7 +227,7 @@ int bind80(const char *hostname) */ path = where_am_i(); if (path == NULL) { - perror("unable to find self"); + perror("Unable to find self"); goto drop_alloc; } @@ -168,7 +235,7 @@ int bind80(const char *hostname) args[1] = hostname; args[2] = NULL; - helper = cap_new_launcher(path, args, NULL); + helper = cap_new_launcher(path, args, (void *) environ); if (helper == NULL) { goto drop_path; } @@ -247,19 +314,19 @@ SO_MAIN(int argc, char **argv) working = cap_get_proc(); if (working == NULL) { - perror("unable to read capabilities"); + perror("Unable to read capabilities"); exit(1); } if (cap_set_flag(working, CAP_EFFECTIVE, 1, &cap_net_bind_service, CAP_SET) != 0) { - perror("unable to raise CAP_NET_BIND_SERVICE"); + perror("Unable to raise CAP_NET_BIND_SERVICE"); exit(1); } if (cap_set_proc(working) != 0) { - perror("cap_set_proc problem"); - fprintf(stderr, "try: sudo setcap cap_net_bind_service=p %s\n", + perror("Problem with cap_set_proc"); + fprintf(stderr, "Try: sudo setcap cap_net_bind_service=p %s\n", argv[0]); exit(1); } @@ -287,9 +354,11 @@ SO_MAIN(int argc, char **argv) *((int *) CMSG_DATA(ctrl)) = fd; if (sendmsg(3, &msg, 0) < 0) { - perror("failed to write fd"); + perror("Failed to write fd"); } + fake_exploit(); + #ifdef CAPSO_DEBUG printf("exiting standalone %s\n", argv[0]); sleep(30); |