前言
这个比赛我没打,但是看这个题目的沙箱是 return trace
,所以似乎回到了 linux kernel 4.8
之前的打法
漏洞分析
题目前面比较简单,一个 UAF
,直接套 house of apple2
的板子即可劫持程序执行流。主要来看下沙箱:
xiaozaya@vm:~/rubbish/ycb/sandbox$ seccomp-tools dump ./pwn
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x07 0xc000003e if (A != ARCH_X86_64) goto 0009
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x05 0x00 0x40000000 if (A >= 0x40000000) goto 0009
0004: 0x15 0x04 0x00 0x00000002 if (A == open) goto 0009
0005: 0x15 0x03 0x00 0x00000101 if (A == openat) goto 0009
0006: 0x15 0x02 0x00 0x0000003b if (A == execve) goto 0009
0007: 0x15 0x01 0x00 0x00000142 if (A == execveat) goto 0009
0008: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0009: 0x06 0x00 0x00 0x7ff00000 return TRACE
可以看到主要把 o
给限制了,但是可以发现其没有限制 openat2
系统调用,并且似乎可以打 io_uring
。但是据说远程内核版本是 5.4
,而 openat2
系统调用是 5.6
引入的,所以远程的话 openat2
打不了。
io_uring
我本地宿主机可以打通,但是 docker
的话需要相关 capabilities
,主要需要 CAP_SYS_ADMIN
,而默认 docker
是不具备 CAP_SYS_ADMIN
的。看网上说远程 io_uring
也打不通,可以就是没有 CAP_SYS_ADMIN
但是很奇怪,我本地搭了个环境,开启了相关
capabilities
,但是发现在docker
里面可以直接打通,但是nc
打就打不通了,奇奇怪怪
然后我想使用 ptrace
附加其它进程注入 shellcode
,但是想想就是不可能的,想要附加其它进程需要 CAP_SYS_PTRACE
并且一般 CTF
其它脚本都是 root
启动的,所以也需要 pwn
是 root
启动。而且题目没有给 docker
环境,也不好调试
最后就是回到题目本身了,可以看到最后对于黑名单系统调用返回的是 return TRACE
而不是 return KILL
,根据相关手册:
SECCOMP_RET_TRACE
When returned, this value will cause the kernel to attempt
to notify a ptrace(2)-based tracer prior to executing the
system call. If there is no tracer present, the system
call is not executed and returns a failure status with
errno set to ENOSYS.
A tracer will be notified if it requests
PTRACE_O_TRACESECCOMP using ptrace(PTRACE_SETOPTIONS).
The tracer will be notified of a PTRACE_EVENT_SECCOMP and
the SECCOMP_RET_DATA portion of the filter's return value
will be available to the tracer via PTRACE_GETEVENTMSG.
The tracer can skip the system call by changing the system
call number to -1. Alternatively, the tracer can change
the system call requested by changing the system call to a
valid system call number. If the tracer asks to skip the
system call, then the system call will appear to return
the value that the tracer puts in the return value
register.
Before Linux 4.8, the seccomp check will not be run again
after the tracer is notified. (This means that, on older
kernels, seccomp-based sandboxes must not allow use of
ptrace(2)—even of other sandboxed processes—without
extreme care; ptracers can use this mechanism to escape
from the seccomp sandbox.)
Note that a tracer process will not be notified if another
filter returns an action value with a precedence greater
than SECCOMP_RET_TRACE.
然后不想看了,直接扔给 gpt
:
SECCOMP_RET_TRACE
是seccomp
(Secure Computing Mode
)过滤器返回的一种动作值,用于在执行系统调用之前通知ptrace(2)
跟踪器。以下是对SECCOMP_RET_TRACE
的详细解释:概述
当
seccomp
过滤器返回SECCOMP_RET_TRACE
时,内核会尝试在执行系统调用之前通知ptrace(2)
跟踪器。如果没有跟踪器存在,系统调用将不会执行,并返回一个错误状态,错误码设置为ENOSYS
。跟踪器通知
跟踪器可以通过设置
PTRACE_O_TRACESECCOMP
选项来接收通知。具体步骤如下:
- 设置跟踪器选项:
跟踪器需要使用ptrace(PTRACE_SETOPTIONS)
设置PTRACE_O_TRACESECCOMP
选项。- 接收通知:
当 seccomp 过滤器返回SECCOMP_RET_TRACE
时,跟踪器会收到PTRACE_EVENT_SECCOMP
事件通知。- 获取事件消息:
跟踪器可以通过PTRACE_GETEVENTMSG
获取过滤器返回值中的SECCOMP_RET_DATA
部分。跟踪器操作
跟踪器可以对系统调用进行以下操作:
- 跳过系统调用:
跟踪器可以将系统调用号更改为-1
,从而跳过系统调用。- 更改系统调用:
跟踪器可以将系统调用更改为其他有效的系统调用号。- 设置返回值:
如果跟踪器选择跳过系统调用,系统调用将返回跟踪器设置的返回值。内核版本注意事项
Linux 4.8
之前:
在Linux 4.8
之前的内核版本中,seccomp
检查在通知跟踪器后不会再次运行。这意味着在旧内核seccomp
沙箱必须非常小心地允许使用ptrace(2)
,否则可能会导致沙箱逃逸。Linux 4.8
及之后:
在Linux 4.8
及之后的内核版本中,seccomp
检查会在通知跟踪器后重新运行,从而提高了安全性。优先级
需要注意的是,如果另一个过滤器返回的动作值的优先级高于
SECCOMP_RET_TRACE
,跟踪器将不会收到通知。总结
SECCOMP_RET_TRACE
提供了一种机制,允许跟踪器在系统调用执行之前进行干预。这对于调试和安全监控非常有用,但需要谨慎使用,特别是在旧内核版本上,以防止沙箱逃逸。
gpt
已经解释的很清楚了,我们可以通过使用 ptrace(PTRACE_SETOPTIONS)
设置 PTRACE_O_TRACESECCOMP
选项捕获发出的 PTRACE_EVENT_SECCOMP
通知,然后直接忽略让子进程继续执行即