Exploit

Exploit部分包括:

  1. 调用C库函数获取vDSO地址,进而根据偏移量获得其中的clock_gettime函数地址。
  2. 根据clock_gettime函数地址对已编译payload进行patch。
  3. 构造用于覆盖vDSO的vdso-payload并保存即将被覆盖的vDSO部分的原始数据。
  4. 创建socket监听指定端口等待反弹shell。
  5. 进行脏牛漏洞利用,借助ptrace成功则向vDSO中写入第3步中的vdso-payload,事实上是借助漏洞带来的高权限实现clock_gettime函数的inline hook。
  6. 等待root进程调用clock_gettime函数(payload中判断调用者是否是root进程,如果不是则直接正常调用clock_gettime函数)
  7. accept接收到反弹shell,创建与客户端通信的socket。
  8. 恢复vDSO。
  9. 将标准输入输出与第7步中的socket对接,至此反弹shell构造完成,用户获得了宿主机上的root执行权限。

原因在于,vDSO没有命名空间隔离的概念,所以只要改写容器内进程映射的vDSO就改写了系统内所有进程的vDSO,根源在于宿主机与容器共享内核。

后文提到的函数如果被中括号括起来,表示其非必需或过于常见且不是利用链的重要组成部分:

上述过程中,排除具体的Payload(在下一节中分析),经过分析,可以得到以下行为特征:

getauxval                 // c lib: 必要,但是系统调用层面检测不出来

[inet_aton]               // c lib
[inet_ntoa]               // c lib

[memcmp]                  // c lib: many times in the progress
[memcpy]                  // c lib: many times in the progress
[memmem]                  // c lib: many times in the progress

[malloc]                  // c lib -> brk or mmap
[free]                    // c lib -> brk or munmap

// 创建反弹shell监听端口,不必需,可能为其他payload接收形式
socket                  // system call
setsockopt              // system call
bind                    // system call
listen                  // system call

// 核心特征部分
pthread_create          // c lib
waitpid                 // system call
pthread_join            // c lib
madvise                 // system call
clone                   // system call
prctl                   // system call
ptrace                  // system call
kill                    // system call
fork                    // system call
usleep                  // c lib

// 反弹shell部分,同上,不必需
accept                  // system call
poll                    // system call
read                    // system call
write                   // system call

close                   // system call
exit                    // system call

行为特征在于,其有两个线程不断在竞争,表现在系统调用上,就是从该进程整体角度来看,会出现一段集中的madvise和ptrace系统调用交错进行的序列。

内存特征:vDSO区域发生修改。一般来说,vDSO应该是不会发生改变的。

Payload

首先需要注意的是,payload千变万化:

  • 实现同一功能的不同payload的特征一般来说具有相似性,核心逻辑应该非常接近,但是整体来说也可能存在差异
  • 实现不同功能的payload的特征可能差别很大,不具有类比性

常用反弹shell的payload:

行为特征(系统调用序列):

[getuid]
[readlink]  // readlink /proc/1/ns/pid
open        // open("/tmp/.x", O_CREAT|O_EXCL, x)
fork
socket      // sockfd = socket(AF_INET, SOCK_STREAM, 0)
connect     // connect(sockfd, (struct sockaddr *)&server, sockaddr_len)
dup2        // dup2(sockfd, STDIN)
dup2        // dup2(sockfd, STDOUT)
dup2        // dup2(sockfd, STERR)
execve      // execve('//bin/sh', NULL, NULL)

文件特征:执行了/bin/sh或其他shell。

参考资料