沙盒逃逸
prctl 函数
1 |
|
CTF中一般只关注两种option:PR_SET_NO_NEW_PRIVS(38)和PR_SET_SECCOMP(22):
prctl(38, 1LL, 0LL, 0LL, 0LL)表示禁用系统调用
option为22时,表示可以设置沙箱规则
如果arg2为SECCOMP_MODE_STRICT(1),则只允许调用read,write,_exit(not exit_group),sigreturn这几个syscall。
如果arg2为SECCOMP_MODE_FILTER(2) 则为过滤模式,其中对syscall的限制通过arg3的结构体,来自定义过滤规则。
seccomp 函数
基于prctl系统调用的机制不够灵活,这个库可以提供一些函数实现prctl类似的效果,库中封装了一些函数,可以不用了解BPF规则而实现过滤。
scmp_filter_ctx是过滤器的结构体类型
seccomp_init对结构体进行初始化
若参数为SCMP_ACT_ALLOW,过滤为黑名单模式,即没有匹配到规则的系统调用将被默认允许;
若参数为SCMP_ACT_KILL ,过滤为白名单模式,即没有匹配到规则的系统调用都会杀死进程,默认不允许所有的syscall。
seccomp_rule_add是添加一条规则。
查看规则
总而言之,无论通过何种办法实现的沙箱,都可以通过seccomp-tools来查看其规则
1 | $ seccomp-tools dump ./rctf_2019_babyheap |
绕过方式
禁用了execve或者system
通过 open read write 来读取flag
example: 高校战疫的 lgd禁用了 open,write,read
openat,所以直接 调用openat,然后除了 read,write,其实还有两个readv,和writev,这些就能绕过限制读取flag,有些连openat都禁用的可以 ptrace 修改syscall
example: zer0pts CTF2020的sycall kit
控制了 open,write,read的参数
具体问题具体分析,参数肯定有可以绕过的方式
如果没有 if (A != ARCH_X86_64) 这个可以同32位的shellcode绕过过,具体的可以参考下 SCTF2020里面的
CoolCode
,利用retfq
切换到32模式,来执行指令