CVE-2021-26708 利用四字节释放特定地址,修改内存

资讯 作者:看雪学院 2021-10-06 22:27:13 阅读:332


本文为看雪论坛优秀文章
看雪论坛作者ID:
inquisiter 



1


漏洞原因


```c
vsock_stream_etssockopt()  {
struct sock *sk;
    struct vsock_sock *vsk;
    const struct vsock_transport *transport;


    /* ... */


    sk = sock->sk;
    vsk = vsock_sk(sk);
    transport = vsk->transport;
    lock_sock(sk);      //  内核sock锁


}
```


vsk 存在本地变量,当sock被条件竞争释放后,这个本地保存的变量将会实现一个四字节的地址写漏洞。


类似这样,setsockopt触发vsock_stream_etssockopt. 但被第二个进程connect竞争等待,这里vsock_stream_connect有一定的几率先于vsock_stream_setsockopt操作释放vsock_sock, 但vsock_stream_setsockopt保存了备份,所以出现了uaf。


2


利用方式



为了在释放后执行virtio_transport_notify_buffer_size, 需要对setsockopt 参数size进行随机变化,绕过参数检查


```c
 if (val != vsk->buffer_size &&
      transport && transport->notify_buffer_size)
        transport->notify_buffer_size(vsk, &val);
```


利用msg_msg机制堆喷占位,实现kmalloc-64内存占用。这时vsock_sock->buf_alloc的位置,也就是msg_msg->security的位置前四字节将会被修改。



3


地址泄露


为了泄露地址,这里利用内核报警   virto_transport_send_pkt_info()。作者gdb分析了崩溃地址的的寄存器地址,分析得出了RCX,  RBX 分别包含了virto_vsock_sock  和  vsock_sock。这个方式还是有点怪,不过应该也可以算可行。


目前我们可以提前释放这两个指针。  


再往后的操作有点杀脑细胞了。


```c
/* one msg_msg structure for each message */
struct msg_msg {
    struct list_head m_list;
    long m_type;
    size_t m_ts;        /* message text size */
    struct msg_msgseg *next;
    void *security;    //无SELinux,这里为NULL
    /* the actual message follows immediately */
};
```
m2的地址是知道的,利用msg_msg占用,二次强制释放。那么这个时候m2可以有两个指针操作,vsock_sock,  msg_msg两个数据结构,再往后 setxattr() & userfaultfd() 精确堆喷占位m2, 伪造m2出的msg->next指针为     vsock_sock地址, 就可以读到m2没有被破坏的数据。



void (*sk_write_space)(struct sock *)函数指针在vsock_sock.sk偏移量688处,被设置为sock_def_write_space()内核函数的地址。它可以用来计算KASLR偏移量。通过这个可以绕过kaslr.


4


制造sk_buff的uaf


作者制造了sk_buff的uaf,这里首先  
```c
struct sk_buff{
unsigned char *head, *data;
}
```
head包含了skb_shared_info和destructor_arg内存块中。而且用户分配2800的内存块户造成skb_kmalloc-4k的内存中。

而vsock_sock中的meme_cgroup也存在于 kmalloc-4k的内存块中。(这里为什么用户分配网络2800会在4k里面我先不分析了,应该作者在exploit for CVE-2017-2636的说明中有解释,先按他说的来)。


```c


1、使用socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)创建一个客户端套接字和32个服务器套接字


2、在用户空间中准备一个2800字节的缓冲区,并用0x42对其memset()


3、用sendto()将这个缓冲区从客户端套接字发送到每个服务器套接字,用于在kmalloc-4k中创建sk_buff对象。在每个可用的CPU上使用`sched_setaffinity()


4、对vsock_sock执行任意读取过程


5、计算可能的sk_buff内核地址为sk_memcg加4096(kmalloc-4k的下一个元素)


6、对这个可能的sk_buff地址执行任意读


7、如果在网络数据的位置找到0x42424242424242lu,则找到真正的sk_buff,进入步骤8。否则,在可能的sk_buff地址上加4096,转到步骤6


8、sk_buff上执行32个pthreads的setxattr()&userfaultfd()堆喷射,并把它们挂在pthread_barrier上


9、对sk_buff内核地址进行任意释放


10、调用pthread_barrier_wait(),执行32个setxattr()覆盖skb_shared_info的堆喷pthreads


11、使用recv()接收服务器套接字的网络消息。


```


这个sk_memcg就是meme_cgroup,存在于vsock_sock.sk中。


也就是说在4k内存块中以4k为步长遍历下,找到存在0x4242数据的块,就是sk_buff的地址。


5


提权结束


> /*
     * A single ROP gadget for arbitrary write:
     *   mov rdx, qword ptr [rdi + 8] ; mov qword ptr [rdx + rcx*8], rsi ; ret
     * Here rdi stores uinfo_p address, rcx is 0, rsi is 1
     */
    uinfo_p->callback = ARBITRARY_WRITE_GADGET + kaslr_offset;
    uinfo_p->desc = owner_cred + CRED_EUID_EGID_OFFSET; /* value for "qword ptr [rdi + 8]" */
    uinfo_p->desc = uinfo_p->desc - 1; /* rsi value 1 should not get into euid */



```c

callback函数指针存储一个ROP gadget 地址,RDI存储callback函数的第一个参数,也就是ubuf_info本身的地址,RDI + 8指向ubuf_info.desc。

gadget 将ubuf_info.desc移动到RDX。现在RDX包含有效用户ID和组ID的地址减一个字节。这个字节很重要:当gadget从 RSI向 RDX指向的内存中写入消息1时,有效的 uid和 gid将被零覆盖。重复同样的过程,直到权限升级到root。
```


6


一些想法


前天看可以利用 shmat 直接泄露内核中init_ipc_ns的地址。利用这个地址可以实现遍历task_struct  找到当前进程的cred地址。如果找到了这个地址,我们利用上面的任意写方式同样可以实现提权,相对可以简单一点感觉。



参考:
https://bbs.pediy.com/thread-269311.htm
http://www.hackdig.com/04/hack-339887.htm



 


看雪ID:inquisiter

https://bbs.pediy.com/user-home-734587.htm

*本文由看雪论坛 inquisiter 原创,转载请注明来自看雪社区



官网:https://www.bagevent.com/event/6334937



# 往期推荐

1.一次针对反fart的加壳apk的脱壳经历

2. CVE-2012-0003 winmm.dll MIDI文件堆溢出漏洞分析及利用

3.驱动级VT技术EPT实现无痕HOOK保护指定进程----VT EPT原理解析和进阶

4. 羊城杯OddCode题解(unicorn模拟调试+求解)

5.从两道0解题看Linux内核堆上msg_msg对象扩展利用

6. Android APP漏洞之战——Broadcast Recevier漏洞详解



公众号ID:ikanxue
官方微博:看雪安全
商务合作:[email protected]



球分享

球点赞

球在看



点击“阅读原文”,了解更多!

在线申请SSL证书行业最低 =>立即申请

[广告]赞助链接:

关注数据与安全,洞悉企业级服务市场:https://www.ijiandao.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注KnowSafe微信公众号
随时掌握互联网精彩
赞助链接