clone

能够生成线程的system call

  • 生成的子进程可以通过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题目频出
  1. 子进程实行seccomp,后续的system call会受到内核级别的全局限制
  2. 但是如果想要执行特定的system call,需要首先通过子进程的过滤器。通过校验后,对system call进行”代理实行”处理(也存在子进程没有独立过滤器的情况)
  3. 通过预先创建的pipe管道,将寄存器及内存信息传递给父进程,代理实行
  4. 父进程通过使用对pipe管道的写入监视等来处理子进程的system call请求
  5. 通信数据通过父进程的过滤器,实行实际的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问题很常见