aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xrun_with_only_cap_net_bind_service.py135
1 files changed, 135 insertions, 0 deletions
diff --git a/run_with_only_cap_net_bind_service.py b/run_with_only_cap_net_bind_service.py
new file mode 100755
index 0000000..9b4d6cc
--- /dev/null
+++ b/run_with_only_cap_net_bind_service.py
@@ -0,0 +1,135 @@
+#!/usr/bin/python3
+
+# resources for cffi:
+# http://eli.thegreenplace.net/2013/03/09/python-ffi-with-ctypes-and-cffi
+
+import cffi
+import os
+import time
+import pwd
+
+pid = os.getpid()
+print('pid:', pid)
+
+ffi = cffi.FFI()
+
+libc = ffi.dlopen('libc.so.6')
+libcap = ffi.dlopen('libcap.so.2')
+#libc.printf(ctypes.c_char_p(b"test\n"))
+
+ffi.cdef('''
+typedef struct _cap_struct *cap_t;
+typedef int cap_value_t;
+typedef enum {
+ CAP_EFFECTIVE=0,
+ CAP_PERMITTED=1,
+ CAP_INHERITABLE=2
+} cap_flag_t;
+
+typedef enum {
+ CAP_CLEAR=0,
+ CAP_SET=1
+} cap_flag_value_t;
+
+int prctl(int option, unsigned long arg2, unsigned long arg3,
+ unsigned long arg4, unsigned long arg5);
+cap_t cap_get_proc(void);
+int cap_set_flag(cap_t cap_p, cap_flag_t flag, int ncap,
+ const cap_value_t *caps, cap_flag_value_t value);
+cap_t cap_init(void);
+int cap_free(void *obj_d);
+int cap_set_proc(cap_t cap_p);
+''')
+
+PR_SET_KEEPCAPS = 8
+PR_SET_NAME = 15
+CAP_EFFECTIVE = 0
+CAP_PERMITTED = 1
+CAP_INHERITABLE = 2
+CAP_CLEAR = 0
+CAP_SET = 1
+
+# generated list with command line below:
+# sed -n 's/^#define \(CAP_.*\) \+\([0-9]\+\).*$/\1 = \2/p' /usr/include/linux/capability.h
+CAP_CHOWN = 0
+CAP_DAC_OVERRIDE = 1
+CAP_DAC_READ_SEARCH = 2
+CAP_FOWNER = 3
+CAP_FSETID = 4
+CAP_KILL = 5
+CAP_SETGID = 6
+CAP_SETUID = 7
+CAP_SETPCAP = 8
+CAP_LINUX_IMMUTABLE = 9
+CAP_NET_BIND_SERVICE = 10
+CAP_NET_BROADCAST = 11
+CAP_NET_ADMIN = 12
+CAP_NET_RAW = 13
+CAP_IPC_LOCK = 14
+CAP_IPC_OWNER = 15
+CAP_SYS_MODULE = 16
+CAP_SYS_RAWIO = 17
+CAP_SYS_CHROOT = 18
+CAP_SYS_PTRACE = 19
+CAP_SYS_PACCT = 20
+CAP_SYS_ADMIN = 21
+CAP_SYS_BOOT = 22
+CAP_SYS_NICE = 23
+CAP_SYS_RESOURCE = 24
+CAP_SYS_TIME = 25
+CAP_SYS_TTY_CONFIG = 26
+CAP_MKNOD = 27
+CAP_LEASE = 28
+CAP_AUDIT_WRITE = 29
+CAP_AUDIT_CONTROL = 30
+CAP_SETFCAP = 31
+CAP_MAC_OVERRIDE = 32
+CAP_MAC_ADMIN = 33
+CAP_SYSLOG = 34
+CAP_WAKE_ALARM = 35
+CAP_BLOCK_SUSPEND = 36
+
+
+uid, gid = 1000, 1000
+
+
+print("before droping caps")
+os.system("cat /proc/{}/status | grep Cap".format(pid))
+
+cap_values = (CAP_NET_BIND_SERVICE, )
+cap_values_temp = (CAP_NET_BIND_SERVICE, CAP_SETUID, CAP_SETGID)
+ccap_values = ffi.new('cap_value_t[]', cap_values)
+ccap_values_temp = ffi.new('cap_value_t[]', cap_values_temp)
+#caps = libcap.cap_get_proc()
+caps = libcap.cap_init()
+print('len cap_values:', len(cap_values))
+libcap.cap_set_flag(caps, CAP_PERMITTED, len(cap_values), ccap_values, CAP_SET)
+libcap.cap_set_flag(caps, CAP_PERMITTED, len(cap_values_temp), ccap_values_temp, CAP_SET)
+libcap.cap_set_flag(caps, CAP_EFFECTIVE, len(cap_values_temp), ccap_values_temp, CAP_SET)
+libcap.cap_set_proc(caps)
+libcap.cap_free(caps)
+
+print("after dropping caps")
+os.system("cat /proc/{}/status | grep Cap".format(pid))
+
+print('result:', libc.prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0))
+#print('result:', libc.prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0))
+
+os.setgroups(os.getgrouplist(pwd.getpwuid(uid)[0], gid))
+os.setgid(gid)
+os.setuid(uid)
+
+print("after setgid/setuid/setgroups")
+os.system("cat /proc/{}/status | grep Cap".format(pid))
+
+#caps = libcap.cap_get_proc()
+caps = libcap.cap_init()
+libcap.cap_set_flag(caps, CAP_PERMITTED, len(cap_values), ccap_values, CAP_SET)
+libcap.cap_set_flag(caps, CAP_EFFECTIVE, len(cap_values), ccap_values, CAP_SET)
+libcap.cap_set_proc(caps)
+libcap.cap_free(caps)
+
+print("after regaining capabilities")
+os.system("cat /proc/{}/status | grep Cap".format(pid))
+
+time.sleep(9999)