Seccomp

securecomputing ,linux下的sandbox,限制哪些syscall可以使用

#include <sys/prctl.h>
#include <linux/seccomp.h>
#include <linux/filter.h>

int main(){
	struct sock_fprog prog;

	prctl(PR_SET_NO_NEW_PRIVS,1,0,0,0);
	prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
}

Seccomp Filter

Allow All Syscall

#include <sys/prctl.h>
#include <linux/seccomp.h>
#include <linux/filter.h>
#include <stdlib.h>

int main(){
	struct sock_filter filter[] = {
		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),//SECCOMP_RET_KILL 所有都不给过
	};
	
	struct sock_fprog prog = {
		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
		.filter = filter,
	};
	

	prctl(PR_SET_NO_NEW_PRIVS,1,0,0,0);
	prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
	
	system("ls");
}

编译

gcc -g sec.c -o sec 

运行

./sec 
sec  sec.c

Disable All Syscall

#include <sys/prctl.h>
#include <linux/seccomp.h>
#include <linux/filter.h>
#include <stdlib.h>

int main(){
	struct sock_filter filter[] = {
		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),
	};
	
	struct sock_fprog prog = {
		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
		.filter = filter,
	};
	

	prctl(PR_SET_NO_NEW_PRIVS,1,0,0,0);
	prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
	
	system("ls");
}

gdb dump memory

gdb-peda$ dump memory dd 0x00007fffffffe2a0 0x00007fffffffe2a0+8

使用libseccomp,地址https://github.com/seccomp/libseccomp,编译并copyscmp_bpf_disasm

./scmp_bpf_disasm < dd
 line  OP   JT   JF   K
=================================
 0000: 0x06 0x00 0x00 0x00000000   ret KILL

Disable execv

#include <sys/prctl.h>
#include <linux/seccomp.h>
#include <linux/filter.h>
#include <stdlib.h>

int main(){
	struct sock_filter filter[] = {
		BPF_STMT(BPF_LD+BPF_W+BPF_ABS,0),		//load进system number
		BPF_JUMP(BPF_JMP+BPF_JEQ,59,1,0),		//等于59就跳过一行
		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
	};
	
	struct sock_fprog prog = {
		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
		.filter = filter,
	};
	

	prctl(PR_SET_NO_NEW_PRIVS,1,0,0,0);
	prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
	
	printf("####\n");
	system("ls");
}

运行

./sec 
####

Bypass Seccomp

  • 没有检查arch
  • 没有挡掉x32下的syscall number

以下函数可以在x86-64和i386之间做切换(切换之后syscall 的number号变化了)

to32:
	mov DWORD [rsp+4] ,0x23
	retf
	
to64:
	mov DWORD [esp+4], 0x33
	retf

x32 syscall:x32是在x86-64下的一种特殊模式

Ptrace

ptrace也可以拦截特定的事件 1.36