• 如何 dump 一个进程的 seccomp filters ?


    如何获取一个进程的 seccomp filters?

    man ptrace 获取到如下内容:

           Since Linux 4.4, the ptrace(2) PTRACE_SECCOMP_GET_FILTER operation can be used to dump a process's seccomp filters.
    
           PTRACE_SECCOMP_GET_FILTER (since Linux 4.4)
                  This operation allows the tracer to dump the tracee's classic BPF filters.
    
                  addr is an integer specifying the index of the filter to be dumped.  The most recently installed filter has the index 0.  If addr is greater than the num‐
                  ber of installed filters, the operation fails with the error ENOENT.
    
                  data is either a pointer to a struct sock_filter array that is large enough to store the BPF program, or NULL if the program is not to be stored.
    
                  Upon  success,  the return value is the number of instructions in the BPF program.  If data was NULL, then this return value can be used to correctly size
                  the struct sock_filter array passed in a subsequent call.
    
                  This operation fails with the error EACCES if the caller does not have the CAP_SYS_ADMIN capability or if the caller is in strict or filter seccomp  mode.
                  If the filter referred to by addr is not a classic BPF filter, the operation fails with the error EMEDIUMTYPE.
    
                  This operation is available if the kernel was configured with both the CONFIG_SECCOMP_FILTER and the CONFIG_CHECKPOINT_RESTORE options.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    manual 信息表明使用 PTRACE_SECCOMP_GET_FILTER 参数就能够获取到进程的 seccomp filter 内容。

    seccomp filter 测试 demo

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    static int install_filter(int nr, int arch, int error) {
      struct sock_filter filter[] = {
        BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (offsetof(struct seccomp_data, arch))),
        BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arch, 0, 3),
        BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (offsetof(struct seccomp_data, nr))),
        BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, nr, 0, 1),
        BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (error & SECCOMP_RET_DATA)),
        BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW),
      };
      struct sock_fprog prog = {
        .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
        .filter = filter,
      };
      if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
        perror("prctl(PR_SET_SECCOMP)");
        return 1;
      }
      return 0;
    }
    
    int main(int argc, char const *argv[]) {
      if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
        perror("prctl(NO_NEW_PRIVS)");
        return 1;
      }
      install_filter(__NR_chroot, AUDIT_ARCH_X86_64, EPERM);
      install_filter(__NR_socket, AUDIT_ARCH_X86_64, EPERM);
      return system(argv[1]);
    }
    
    • 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

    上述文件给当前进程注册两个 seccomp filter 规则,用以禁止进程使用 chroot 与 socket 系统调用,然后使用 system 函数执行传递的命令。

    将上述文件保存为 seccomp.c 并编译生成 seccomp 程序。

    获取 seccomp filter 的示例 demo

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    int main(int argc, char const *argv[]) {
    	struct sock_filter *filter = NULL;
    	int number = 0;
    	int index = -1;
    	int pid;
    	
    	if (argc != 3) {
    		printf("%s pid filter-index", argv[0]);
    		exit(-1);
    	}
    	pid = atoi(argv[1]);
    	index = atoi(argv[2]);
    	
    	memset(&filter, 0x00, sizeof(filter));
    	ptrace(PTRACE_ATTACH, pid);
    
    	number = ptrace(PTRACE_SECCOMP_GET_FILTER, pid, (void *)index, NULL);
    	filter = malloc(sizeof(struct sock_filter) * number);
    	ptrace(PTRACE_SECCOMP_GET_FILTER, pid, (void *)index, (void *)filter);
    	
    	for (int i = 0; i < number; i++) {
    		printf("0x%x%x%x\n", filter[i].code, filter[i].jt, 
    				filter[i].jf, filter[i].k);
    	}
    }
    
    • 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

    上述代码首先使用 ptrace跟踪目标进程,然后使用 PTRACE_SECCOMP_GET_FILTER参数执行 ptrace并将最后一个参数设置为 NULL来获取 index 指向的 seccomp filter 的 bpf 字节码长度,然后申请相应大小的 sock_filter。此后重新使用 PTRACE_SECCOMP_GET_FILTER参数执行 ptrace获取到进程的 seccomp filter,最后将获取到的指令码打印出来。

    将上述文件保存为 dump.c 并编译生成 dump 程序。

    给 dump 程序单独添加权限

    执行如下命令添加 cap_sys_admin 权限:

    [longyu@debian] tmp $ sudo setcap cap_sys_admin+ep ./dump
    
    • 1

    查看添加后的权限:

    [longyu@debian] tmp $ sudo getcap ./dump
    ./dump cap_sys_admin=ep
    
    • 1
    • 2

    成功添加权限后就可以使用 dump 程序来 dump 进程的 seccomp filter 内容。

    dump 一个进程的 seccomp filters 的示例步骤

    1. 在一个终端中执行 ./seccomp bash 命令给 bash 命令添加 seccomp filter
    2. 获取 bash 命令的 pid
    3. 在另外一个终端使运行 dump 程序并指定 pid 参数与 seccomp filter index

    测试示例如下:

    [longyu@debian] tmp $ ./dump 33449 0
    0x2000
    0x1503
    0x2000
    0x1501
    0x600
    0x600
    [longyu@debian] tmp $ ./dump 33449 1
    0x2000
    0x1503
    0x2000
    0x1501
    0x600
    0x600
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    获取成功!

    注意事项

    1. 在使用 PTRACE_SECCOMP_GET_FILTER参数执行 ptrace前需要先使用 PTRACE_ATTACH 与待 trace 进程的 pid 参数来调用 ptrace trace 到目标进程中。
    2. 进程支持 PTRACE_SECCOMP_GET_FILTER 的最小权限为 cap_sys_admin,setcap 赋予此权限后不需要 root 权限就能够成功 dump。
    3. seccomp 支持同时添加多个 filter 且可被子进程继承
  • 相关阅读:
    MAUI Blazor 权限经验分享 (定位,使用相机)
    我的创作纪念日
    学网安兴趣最重要
    2023国赛数学建模C题思路分析 - 蔬菜类商品的自动定价与补货决策
    【第二章 数据的表示和运算】d1
    激活函数总结(四十二):激活函数补充(SSFG、Gumbel Cross Entropy)
    淘宝/天猫电商API接口详情
    SpringCloud之nacos
    JVM哪些区域可能出现内存溢出,哪些地方需要GC?
    2022年合肥市蜀山区信息学区赛(小学组)
  • 原文地址:https://blog.csdn.net/Longyu_wlz/article/details/126256405