-
Notifications
You must be signed in to change notification settings - Fork 9
/
capable_example.txt
135 lines (112 loc) · 6.5 KB
/
capable_example.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
Demonstrations of capable, the Linux eBPF/bcc version.
capable traces calls to the kernel cap_capable() function, which does security
capability checks, and prints details for each call. For example:
# ./capable.py
TIME UID PID COMM CAP NAME AUDIT
22:11:23 114 2676 snmpd 12 CAP_NET_ADMIN 1
22:11:23 0 6990 run 24 CAP_SYS_RESOURCE 1
22:11:23 0 7003 chmod 3 CAP_FOWNER 1
22:11:23 0 7003 chmod 4 CAP_FSETID 1
22:11:23 0 7005 chmod 4 CAP_FSETID 1
22:11:23 0 7005 chmod 4 CAP_FSETID 1
22:11:23 0 7006 chown 4 CAP_FSETID 1
22:11:23 0 7006 chown 4 CAP_FSETID 1
22:11:23 0 6990 setuidgid 6 CAP_SETGID 1
22:11:23 0 6990 setuidgid 6 CAP_SETGID 1
22:11:23 0 6990 setuidgid 7 CAP_SETUID 1
22:11:24 0 7013 run 24 CAP_SYS_RESOURCE 1
22:11:24 0 7026 chmod 3 CAP_FOWNER 1
22:11:24 0 7026 chmod 4 CAP_FSETID 1
22:11:24 0 7028 chmod 4 CAP_FSETID 1
22:11:24 0 7028 chmod 4 CAP_FSETID 1
22:11:24 0 7029 chown 4 CAP_FSETID 1
22:11:24 0 7029 chown 4 CAP_FSETID 1
22:11:24 0 7013 setuidgid 6 CAP_SETGID 1
22:11:24 0 7013 setuidgid 6 CAP_SETGID 1
22:11:24 0 7013 setuidgid 7 CAP_SETUID 1
22:11:25 0 7036 run 24 CAP_SYS_RESOURCE 1
22:11:25 0 7049 chmod 3 CAP_FOWNER 1
22:11:25 0 7049 chmod 4 CAP_FSETID 1
22:11:25 0 7051 chmod 4 CAP_FSETID 1
22:11:25 0 7051 chmod 4 CAP_FSETID 1
Checks where AUDIT is 0 are ignored by default, which can be changed
with -v but is more verbose.
We can show the TID and INSETID columns with -x.
Since only a recent kernel version >= 5.1 reports the INSETID bit to cap_capable(),
the fallback value "N/A" will be displayed on older kernels.
# ./capable.py -x
TIME UID PID TID COMM CAP NAME AUDIT INSETID
08:22:36 0 12869 12869 chown 0 CAP_CHOWN 1 0
08:22:36 0 12869 12869 chown 0 CAP_CHOWN 1 0
08:22:36 0 12869 12869 chown 0 CAP_CHOWN 1 0
08:23:02 0 13036 13036 setuidgid 6 CAP_SETGID 1 0
08:23:02 0 13036 13036 setuidgid 6 CAP_SETGID 1 0
08:23:02 0 13036 13036 setuidgid 7 CAP_SETUID 1 1
08:23:13 0 13085 13085 chmod 3 CAP_FOWNER 1 0
08:23:13 0 13085 13085 chmod 4 CAP_FSETID 1 0
08:23:13 0 13085 13085 chmod 3 CAP_FOWNER 1 0
08:23:13 0 13085 13085 chmod 4 CAP_FSETID 1 0
08:23:13 0 13085 13085 chmod 4 CAP_FSETID 1 0
08:24:27 0 13522 13522 ping 13 CAP_NET_RAW 1 0
[...]
This can be useful for general debugging, and also security enforcement:
determining a whitelist of capabilities an application needs.
The output above includes various capability checks: snmpd checking
CAP_NET_ADMIN, run checking CAP_SYS_RESOURCES, then some short-lived processes
checking CAP_FOWNER, CAP_FSETID, etc.
To see what each of these capabilities does, check the capabilities(7) man
page and the kernel source.
It is possible to include a kernel stack trace to the capable events by passing
-K to the command:
# ./capable.py -K
TIME UID PID COMM CAP NAME AUDIT
15:32:21 1000 10708 fetchmail 7 CAP_SETUID 1
cap_capable+0x1 [kernel]
ns_capable_common+0x7a [kernel]
__sys_setresuid+0xc8 [kernel]
do_syscall_64+0x56 [kernel]
entry_SYSCALL_64_after_hwframe+0x49 [kernel]
15:32:21 1000 30047 procmail 6 CAP_SETGID 1
cap_capable+0x1 [kernel]
ns_capable_common+0x7a [kernel]
may_setgroups+0x2f [kernel]
__x64_sys_setgroups+0x18 [kernel]
do_syscall_64+0x56 [kernel]
entry_SYSCALL_64_after_hwframe+0x49 [kernel]
Similarly, it is possible to include user-space stack with -U (or they can be
used both at the same time to include user and kernel stack).
Some processes can do a lot of security capability checks, generating a lot of
ouput. In this case, the --unique option is useful to only print once the same
set of capability, pid (or cgroup if --cgroupmap is used) and kernel/user
stacks (if -K or -U are used).
# ./capable.py -K -U --unique
The --cgroupmap option filters based on a cgroup set. It is meant to be used
with an externally created map.
# ./capable.py --cgroupmap /sys/fs/bpf/test01
For more details, see docs/special_filtering.md
USAGE:
# ./capable.py -h
usage: capable.py [-h] [-v] [-p PID] [-K] [-U] [-x] [--cgroupmap CGROUPMAP]
[--mntnsmap MNTNSMAP] [--unique]
Trace security capability checks
optional arguments:
-h, --help show this help message and exit
-v, --verbose include non-audit checks
-p PID, --pid PID trace this PID only
-K, --kernel-stack output kernel stack trace
-U, --user-stack output user stack trace
-x, --extra show extra fields in TID and INSETID columns
--cgroupmap CGROUPMAP
trace cgroups in this BPF map only
--mntnsmap MNTNSMAP trace mount namespaces in this BPF map only
--unique don't repeat stacks for the same pid or cgroup
examples:
./capable # trace capability checks
./capable -v # verbose: include non-audit checks
./capable -p 181 # only trace PID 181
./capable -K # add kernel stacks to trace
./capable -U # add user-space stacks to trace
./capable -x # extra fields: show TID and INSETID columns
./capable --unique # don't repeat stacks for the same pid or cgroup
./capable --cgroupmap mappath # only trace cgroups in this BPF map
./capable --mntnsmap mappath # only trace mount namespaces in the map