clone
能够生成线程的system call
- 适用于sandbox,出现频率非常高
- clone(2)和clone(3)有区别,这里使用clone(3)进行说明
- https://linuxjm.osdn.jp/html/LDP_man-pages/man2/clone.2.html
- 生成的子进程可以通过fn()恢复
- 生成的子进程,使用child_stack作为stack
- 因为使用父进程相同的stack会产生corrupt
- flags可以指定各种,sandbox问题中这些比较多:
- CLONE_THREAD:与父进程相同的线程组(线程必须)
- CLONE_SIGHAND:与父进程共享信号处理程序表(线程必须)
- CLONE_FILES:与父进程共享文件目录
- CLONE_FS:与父进程共享文件系统信息
- CLONE_VM:与父进程共享内存空间(线程必须)
特别是CLONE_VM,重要
与父进程共享内存空间
- 没有CLONE_VM的情况,内存空间是复制后独立的
- 指定CLONE_VM的情况,共享内存空间
CLONE_FILES也很常见
与父进程共享文件目录
- 没有指定CLONE_FILES的情况,fd是复制后独立的
- 指定CLONE_FILES的情况,共享文件目录fd
clone与seccomp
clone(flags=CLONE_VM|…)和seccomp()很适合结合使用
- 两者结合的sandbox题目频出
- 子进程实行seccomp,后续的system call会受到内核级别的全局限制
- 但是如果想要执行特定的system call,需要首先通过子进程的过滤器。通过校验后,对system call进行”代理实行”处理(也存在子进程没有独立过滤器的情况)
- 通过预先创建的pipe管道,将寄存器及内存信息传递给父进程,代理实行
- 父进程通过使用对pipe管道的写入监视等来处理子进程的system call请求
- 通信数据通过父进程的过滤器,实行实际的system call(也存在父进程没有独立过滤器的情况)
- 即使子进程实行了seccomp,也与父进程无关,父进程可以自由的进行system call
- 因为内存空间和fd是共享的,某些system call的结果会反映在子进程中。(例如通过mmap生成新的内存区域会反映在子进程中,通过open打开文件,那么子进程也可以使用该fd)
- 因此可能会有非预期解法,导致子进程执行某些system call
- 这种类型的题目考点是“如何绕过独立过滤器”
- seccomp基本不可绕过
- 绕过对象可以是子进程的独立过滤器,也可以是父进程的
没有CLONE_VM的模式
存在clone(flags=CLONE_VM|…)这样不使用CLONE_VM的模式
- 除了使用下面这样的pipe管道进行数据交换外,还使用ptrace, process_vm_readv,process_vm_writev等
常见模式
常见模式1(有无CLONE_VM皆可)
- 自己独立过滤器的参数检查比较容易bypass
- 检查范围的溢出,index溢出,特殊字符,竞争等
常见模式2(有无CLONE_VM皆可)
- 首先子进程能够执行任意代码
- stack BOF,heap BOF,FSB,UAF,TypeConfusion,Race等
- 自己独立过滤器隐含假设条件被打破,进行调用
- system call参数,调用源,调用计数,上下文
常见模式3(有CLONE_VM)
- 利用子进程中的漏洞,创建read/write原语(一系列任意内存读写的输入)
- 重复内存泄漏,使ASLR无效
- 因为内存由CLONE_VM共享,因此父进程使用的内存被重写,就能够禁用或者绕过父进程的独立过滤器
常见模式4(无CLONE_VM)
- 子进程可以执行任意代码
- 从子进程向父进程发送意外数据,利用父进程的漏洞
- 造成父进程的任意代码执行
- 类似模式1和2,禁用父进程的独立过滤器
clone总结
- CLONE_VM,CLONE_FILES比较多
- 皆在通过创建特殊的进程来构造sandbox问题
- sandbox问题很常见