Linux内核漏洞详情及其Exp
2021-05-07 10:42:26 Author: mp.weixin.qq.com(查看原文) 阅读量:85 收藏


文章来源: SecTr安全团队

概述

本文中详细介绍了Linux内核新引入的io_uring子系统中的UAF漏洞CVE-2021-20226。该漏洞导致任意文件结构释放后重用,可用于在内核中提升权限,影响范围为Linux内核v5.6至v5.7。

漏洞详情

Linux内核v5.1引入了一个名为io_uring新异步I/O接口。io_uring通过批处理I/O操作系统调用运行,因此可以在一个系统调用中执行多个I/O操作。
Linux内核v5.6IORING_OP_CLOSE操作实现中存在漏洞。当系统调用将files_struct传递给内核线程时,io_grab_files()不会在注释(1)处增加参考计数,从而导致释放的文件结构在之后被访问。
static int io_grab_files(struct io_kiocb *req) { // ...      rcu_read_lock();     spin_lock_irq(&ctx->inflight_lock);spin_lock_irq(&ctx->inflight_lock);      if (fcheck(ctx->ring_fd) == ctx->ring_file) {         list_add(&req->inflight_entry, &ctx->inflight_list);         req->flags |= REQ_F_INFLIGHT;         req->work.files = current->files;  // <-- (1)         ret = 0;     }     spin_unlock_irq(&ctx->inflight_lock);     rcu_read_unlock();      return ret; }

漏洞利用(Exp)

map_lookup_elem()map_update_elem()函数都可以用于利用该漏洞。
static int map_lookup_elem(union bpf_attr *attr) {     void __user *ukey = u64_to_user_ptr(attr->key);     int ufd = attr->map_fd; // ...     f = fdget(ufd);          // <-- (2)     map = __bpf_map_get(f); // ...     key = __bpf_copy_key(ukey, map->key_size); key = __bpf_copy_key(ukey, map->key_size); // <-- (3)     if (IS_ERR(key)) {         err = PTR_ERR(key);         goto err_put;     }      value_size = bpf_map_value_size(map);  // <-- (4)      err = -ENOMEM;     value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);     if (!value)         goto free_key;      err = bpf_map_copy_value(map, key, value, attr->flags); // <-- (5)     if (err)         goto free_value;      err = -EFAULT;     if (copy_to_user(uvalue, value, value_size) != 0) // <-- (6)         goto free_value; // ... }
注释(2)fdget()是一个优化函数,如果当前任务是单线程的,则不会增加参考计数。返回的文件结构 f 可以在之后的IORING_OP_CLOSE中释放注释(3)处的__bpf_copy_key()系统调用实际上是copy_from_user()的封装。这使我们能够使用userfaultfd生成竞争条件,并触发漏洞。此时,文件结构 f 及其对应的映射被释放。可通过注释(4)(5)处的虚假数据重新分配映射的内存。最终,我们可以在注释(6)处读取任意内存并向用户模式暴露。
该漏洞利用时间表如下所示:
recvmsg()函数用于定时控制。通过喷射setxattr()即可伪造被释放的bpf_map。通过map_update_elem()即可实现任意写入。fdget()条件的存在,使得该漏洞利用方法仅限于单核环境。

如侵权请私聊公众号删文


文章来源: http://mp.weixin.qq.com/s?__biz=MzAxMjE3ODU3MQ==&mid=2650510324&idx=3&sn=186109eb0603d0c0632633461f883c50&chksm=83baf610b4cd7f0650183c5319103e857ff5dca7d704040934fb318296ef4251cc92a84c92fe#rd
如有侵权请联系:admin#unsafe.sh