Linux bcc 跟踪安全功能

您的应用程序使用了哪些 Linux 安全功能?我最近开发了一个新工具,能够实时打印出能力检查:

#有能力
TIME UID PID COMM CAP NAME AUDIT
22:11:23 114 2676 snmpd 12 CAP_NET_ADMIN 1
22:11:23 0 6990 运行 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 运行 24 CAP_SYS_RESOURCE 1
22:11:24 0 7026 chmod 3 CAP_FOWNER 1
[...]

能够使用bcc,一个前端和一组使用新的 Linux 增强 BPF 跟踪功能的工具。能力通过使用带有 kprobes 的 BPF 来动态跟踪内核 cap_capable() 函数,然后使用表将能力索引映射到输出中看到的名称。这是源代码:它非常简单。
我写它是因为我的同事 Michael Wardrop 询问我们的应用程序实际使用了哪些安全功能。给定一个列表,我们可以使用 setcap(8)(或其他软件)通过只允许必要的功能来提高应用程序的安全性。
非审计检查
cap_capable() 函数有一个审计参数,它指示能力检查是否应该写入审计消息(如果已配置)。默认情况下,我只在正确的地方打印能力检查,但能力也可以使用 -v 选项跟踪所有检查:
#有能力 -h
用法:有能力 [-h] [-v] [-p PID]

跟踪安全能力检查

可选参数:
-h, --help 显示此帮助信息并退出
-v, --verbose 包括非审计检查
-p PID, --pid PID 只跟踪这个 PID

例子:
./capable # 跟踪能力检查
./capable -v # 详细:包括非审计检查
./capable -p 181 # 仅跟踪 PID 181
以下是一些非审计事件:

#有能力 -v
TIME UID PID COMM CAP NAME AUDIT
20:53:45  60004  22061  lsb_release      21   CAP_SYS_ADMIN        0
20:53:45  60004  22061  lsb_release      21   CAP_SYS_ADMIN        0
20:53:45  60004  22061  lsb_release      21   CAP_SYS_ADMIN        0
20:53:45  60004  22061  lsb_release      21   CAP_SYS_ADMIN        0
20:53:45  60004  22061  lsb_release      21   CAP_SYS_ADMIN        0
20:53:45  60004  22061  lsb_release      21   CAP_SYS_ADMIN        0
[...]

这些都是什么?
我将从 security/commoncap.c 中的 cap_capable() 函数原型开始:
int cap_capable(const struct cred *cred, struct user_namespace *targ_ns,
国际上限,国际审计)
现在我可以使用 bcc 的跟踪程序来检查这些调用(请耐心等待),假设 cap 将是 arg3,并且审计 arg4(来自上面的原型):

# trace 'cap_capable "cap: %d, audit: %d", arg3, arg4'
TIME     PID    COMM         FUNC             -
20:56:18 25535  lsb_release  cap_capable      cap: 21, audit: 0
20:56:18 25535  lsb_release  cap_capable      cap: 21, audit: 0
20:56:18 25535  lsb_release  cap_capable      cap: 21, audit: 0
20:56:18 25535  lsb_release  cap_capable      cap: 21, audit: 0
20:56:18 25535  lsb_release  cap_capable      cap: 21, audit: 0
[...]

该单行程序与我的功能强大的程序非常相似,只是它缺少带有人类可读翻译的“NAME”列。
我真的这样做了,所以我可以添加(新添加的)-K 和 -U 选项,它们打印内核和用户级堆栈跟踪。 我将只使用-K:

# trace -K 'cap_capable "cap: %d, audit: %d", arg3, arg4'
TIME     PID    COMM         FUNC             -
[...]
20:59:58 30607  lsb_release  cap_capable      cap: 21, audit: 0
    Kernel Stack Trace:
        ffffffff813659d1 cap_capable
        ffffffff813684bb security_vm_enough_memory_mm
        ffffffff811deda6 expand_downwards
        ffffffff811def64 expand_stack
        ffffffff81234321 setup_arg_pages
        ffffffff8128c10b load_elf_binary
        ffffffff81234cee search_binary_handler
        ffffffff8128b7ff load_script
        ffffffff81234cee search_binary_handler
        ffffffff8123635a do_execveat_common.isra.35
        ffffffff812367da sys_execve
        ffffffff81003bae do_syscall_64
        ffffffff81861ca5 return_from_SYSCALL_64

20:59:58 30607  lsb_release  cap_capable      cap: 21, audit: 0
    Kernel Stack Trace:
        ffffffff813659d1 cap_capable
        ffffffff813684bb security_vm_enough_memory_mm
        ffffffff811df623 mmap_region
        ffffffff811dff4b do_mmap
        ffffffff811c122a vm_mmap_pgoff
        ffffffff811c1295 vm_mmap
        ffffffff8128bb93 elf_map
        ffffffff8128c271 load_elf_binary
        ffffffff81234cee search_binary_handler
        ffffffff8128b7ff load_script
        ffffffff81234cee search_binary_handler
        ffffffff8123635a do_execveat_common.isra.35
        ffffffff812367da sys_execve
        ffffffff81003bae do_syscall_64
        ffffffff81861ca5 return_from_SYSCALL_64
[...]

惊人的。所以这些来自security_vm_enough_memory_mm()。通过阅读源代码,我看到它用于为 root 保留一些内存。如果缺少该功能,这不是硬故障。它并不是真正的安全检查,因此它禁用了审计。
我应该为有能力的工具添加一个 -K 选项,这样它也可以打印堆栈跟踪。
较旧的内核
要使用有能力,您需要 4.4 内核。要使用 -K 选项,4.6。
这是使用我较旧的perf-tools集合的版本,它使用 ftrace 并且应该适用于更旧的内核,包括 3.x 系列:

# ./perf-tools/bin/kprobe -s 'p:cap_capable cap=%dx audit=%cx' 'audit != 0'
跟踪 kprobe cap_capable。Ctrl-C 结束。
             运行 4440 [003] d... 6417394.367486: cap_capable: (cap_capable+0x0/0x70) cap=0x18 audit=0x1
             运行 4440 [003] d... 6417394.367492:
 => ns_capable_common
 => 有能力
 => do_prlimit
 => SyS_setrlimit
 => entry_SYSCALL_64_fastpath
           chmod-4453 [006] d... 6417394.399020: cap_capable: (cap_capable+0x0/0x70) cap=0x3 audit=0x1
           chmod-4453 [006] d... 6417394.399027:
 => ns_capable_common
 => ns_capable
 => inode_owner_or_capable
 => inode_change_ok
 => xfs_setattr_nonsize
 => xfs_vn_setattr
 => 通知更改
 => chmod_common
 => SyS_fchmodat
 => entry_SYSCALL_64_fastpath
           chmod-4453 [006] d... 6417394.399035: cap_capable: (cap_capable+0x0/0x70) cap=0x4 audit=0x1
           chmod-4453 [006] d... 6417394.399037:
 => ns_capable_common
 => 能力_wrt_inode_uidgid
 => inode_change_ok
 => xfs_setattr_nonsize
 => xfs_vn_setattr
 => 通知更改
 => chmod_common
 => SyS_fchmodat
 => entry_SYSCALL_64_fastpath
           chmod-4455 [007] d... 6417394.402524: cap_capable: (cap_capable+0x0/0x70) cap=0x4 audit=0x1
           chmod-4455 [007] d... 6417394.402529:
 => ns_capable_common
 => 能力_wrt_inode_uidgid
 => inode_change_ok
 => xfs_setattr_nonsize
 => xfs_vn_setattr
 => 通知更改
 => chmod_common
 => SyS_fchmodat
 => entry_SYSCALL_64_fastpath
[...]

这是使用我的 kprobe 工具的单线器。它也(目前)有点难以使用:我需要知道这些参数将在哪些寄存器中:上面的示例仅适用于 x86_64。
目前为止就这样了。快乐的黑客。

转载翻译自: https://www.brendangregg.com