技术社区
安全培训
技术社群
积分商城
先知平台
漏洞库
历史记录
清空历史记录
相关的动态
相关的文章
相关的用户
相关的圈子
相关的话题
注册
登录
CVE-2023-2598 内核提权详细分析
默文
历史精选
190浏览 · 2025-03-07 05:44
返回文档
CVE-2023-2598 内核提权详细分析
漏洞简介
漏洞编号
: CVE-2023-2598
影响版本
:6.3 <= Linux Kernel < v6.3.2
漏洞产品
: linux kernel - io_uring & io_sqe_buffer_register io_uring & folio
利用效果
: 本地提权
环境搭建
复现环境
:qemu + linux kernel v6.3.1
环境附件:
mowenroot/Kernel
复现流程
: 执行exp后,账号:hacker的root用户被添加。su hacker完成提权。
漏洞原理
漏洞本质是
物理地址越界读取(oob)
。
io_uring
模块中提供
io_sqe_buffers_register
来创建一个
Fixed Buffers
的区域,这块区域会锁定,不能被交换,专门用来数据的读取。但是在进行连续多个大页的优化,尝试合并页的时候,使用了新机制
folio
,
folio
是物理内存、虚拟内存都连续的
page
集合,在进行页合并时只判断
page
是否属于当前复合页,而未判断是否连续。当用户传入同一个物理地址时,长度是整个复合页长度,地址是指向一个地址,这个时候就会造成
物理地址越界读取
。
漏洞技术点涉及 io_uring 、复合页机制folio,下面详细分析。
参考链接:
CVE-2023-2598 io_uring内核提权分析 | CTF导航
https://chompie.rip/Blog+Posts/Put+an+io_uring+on+it+-+Exploiting+the+Linux+Kernel
https://anatomic.rip/cve-2023-2598/#folio
虽然参考了很多资料,但是网传的EXP手法都过于复杂,并且还需要内核基地址的校准,并没有通杀性,作者在这里使用这个漏洞转化为稳定强大的“脏牛”。
folio
Linux
内核
v5.16
引入了内存管理特性
folio
,旨在解决传统
struct page
在处理内存页时的效率问题,特别是在管理大块内存和页缓存(page cache)时。
在
Linux
内核中,物理内存以
页(page)
为单位管理,每个页对应一个
struct page
结构体。传统方式中,无论是 4KB 的小页还是 2MB 的大页(如透明大页,THP),每个页都需独立的
struct page
实例,说人话就是不管你申请多少大的内存,我都
4KB、4KB
的给你。但是吧,可能在内存操作少的时候无感,但使用大页的时候开销就会变的巨大。总结一下就会有以下缺点:
●
内存开销大
:每页的元数据(
struct page
)占用额外内存,尤其是大页场景下,多个连续页的元数据导致冗余。
●
操作效率低
:处理大块内存时,需遍历每个页的
struct page
,这就有点搬砖的意思了。
●
代码复杂度高
:内存管理代码需区分单页与复合页,逻辑复杂。在没引入
folio
之前,操作复合页很复杂。
在没
folio
之前都是通过 "复合页" ,来抽象多个物理连续页的。当
__alloc_pages
分配标志GFP FLAGS指定了
__GFP_COMP
,那么内核必须将这些页组合成复合页,第一个页称为
head page
,其余的所有页称为
tail page
,
复合页通过以下方式区分
head
和
tail
页:
(1) Head 页
●
PG_head 标志
:
head_page ->flags
设置
PG_head
,表示它是复合页的首个页。
●
private 字段
:head 页的
page->private
指向自身,即
head->private = (unsigned long)head
。
(2) Tail 页
●
compound_head 字段
:
compound_head
上的最后一位设置为
1
,表示
tail page
。
●
private 字段
:tail 页的
page->private
指向 head 页,即
tail->private = (unsigned long)head
。
复合页的总页数由分配时的
order
决定,计算公式为
2^order
。例如,
order=3
表示复合页包含
8
个页。总页数信息存储为第一个 tail 页的
compound_order
:通过
compound_order()
函数从
compound_order
中提取
order
值,进而计算总页数。
看到这里可能以及感觉到有点复杂了,当一个概念强加在另一个概念上,这就会变的非常糅杂。“复合页”就是如此,而
folio
是一个全新的结构体,相对概念也不干扰
page
。所以在这个时候
Linus
认为
folio
的优势也是明显的,能够更直白的处理复合页,避免一些混乱的问题,最终
folio
被采用。
folio 是 过去复合页的替代品,来看一下两者对比的基本操作。显而易见的
folio
更容易理解操作。
Folio 机制
的引入,通过将一个或多个连续的物理页抽象为逻辑上的
folio 单元
,统一管理单页和大页,优化内存操作效率。
folio
本质上可以看作是一个集合,是
物理连续、虚拟连续
的
2^n
次的
PAGE_SIZE
的一些
bytes
的集合,n可以是0,也就是说单个页也算是一个folio。
Folio
并非全新结构,而是对
struct page
的封装扩展:
而且
folio
里面还内嵌了
page
结构。
漏洞分析
关于io_uring的一些基础知识之前的文章已经详细介绍过,如果师傅们感兴趣可以看看之前的文章。接下来只介绍漏洞相关的点。
NVD描述
:在 Linux 内核中io_uring的固定缓冲区注册代码(io_sqe_buffer_register io_uring/rsrc.c)中发现一个缺陷,该缺陷允许对缓冲区末尾以外的物理内存进行越界访问。此缺陷可实现完全本地权限提升。
io_uring_register
提供了接口
io_sqe_buffer_register
来注册一块 fixed_buffers 空间,这块区域会锁定,不能被交换,专门用来数据的读取。申请的大小和锁定地址都有用户来控制。
io_sqe_buffers_register
「1」 首先就会使用
io_buffers_map_alloc
为
上下文(ctx)
分配用户缓冲区数组,分配数组大小由用户控制。
「2」 然后遍历每个
ctx->user_bufs[]
来进行初始化操作,先复制用户参数到内核态的
kernel_iov
,用户控制的
usr_iov
主要就两个字段
{iov_base,iov_len}
,所以在申请缓冲区参数完全由用户控制。调用
io_sqe_buffer_register
传入
iov,ctx->user_bufs[n]
进一步对每个页完成注册。
io_sqe_buffer_register
「1」 使用
io_pin_pages()
对用户传入
iov
锁定对应长度的物理页,作为io_uring的共享内存区域。
「2」 然后开始连续多个大页的优化,尝试合并页。 如果
nr_pages > 1
,就开始合并页,这里的
nr_pages
取决于用户的
iov_len
,比如说
iov_len = 50* PAGE_SIZE;
,那在这里就有50个页的长度,在这
nr_pages == 50>1
,就可以开始尝试合并。
「3」 漏洞点就在于此: 在循环判断当前页是否属于同一复合页的时候,只判断是否在同一复合页,没判断是否连续。在最开始介绍
folio
时,就很明确说明
folio
是
虚拟连续、物理连续
的一块内存空间。那当我传入所有的
page
虽然虚拟地址连续,但都指向一个物理地址。当你在读写时
kernel
认为你的读取的长度和地址都是连续的没问题,但实际都在一个固定的物理地址读取,长度却是整个复合页的长度。
「4」 继续跟进,如果满足复合页要求,会删除其他
page
的引用,只保留第一个(保留pages[0]),动态申请
struct io_mapped_ubuf *imu
空间包含
nr_pages
个
bvec
。调用
io_buffer_account_pin()
,锁定
pages
到
imu
,然后把
iov
参数传递给
imu
。这里的
imu
通过指针传递给
&ctx->user_bufs[i]
,说人话就是这些操作都是对
user_bufs[i]
进行操作。所以后续用户可以直接对这块区域进行操作。
网传EXP复现
网传EXP地址:
ysanatomic/io_uring_LPE-CVE-2023-2598
这个师傅使用的手法是通过设置
sock
然后oob找到sock,然后劫持
proto
为
CALL_USERMODEHELPER_EXEC
来提权。
缺点也很明显,依赖于内核基地址,不通用,且伪造
subprocess_info
过于复杂,并且有崩溃情况。
我直接修改了
sock->ops->set_rcvlowat.
然后导致加入work队列报错。也就懒得继续修复了,拿到这个漏洞的时候我就在想物理地址越界读写,直接转换为dirty_pipe对pipe的flags进行篡改,然后对只读文件进行篡改,但是我都对文件进行篡改了,那就直接劫持filp。后面开始实验。
〔1〕 初始化:绑定CPU,注册io_uring,设置最大可打开文件数 (把rlim_cur设置为rlim_max),
nr_memfds
—— 映射漏洞物理页的文件最大打开数量。
nr_sockets
最大打开
socket
数量。
〔2〕 创建
receiver_fd
,映射
receiver_buffer
内存(
mmap()
),用于存放数据(越界读取的数据和伪造的数据);
〔3〕 打开
nr_sockets
个 socket :
设置 sk_pacing_rate / sk_max_pacing_rate == 0xdeadbeefdeadbeef, 便于找到本sock
原作者使用sk_sndbuf ,设置sk->sk_sndbuf = max((fd+4608)*2, 4608), 通过
sk->sk_sndbuf
值可以识别其所属的fd。
但是在
sock
中有更简单的标识符
SO_RCVBUF
,设置接受缓冲区大小,在这里
fd
只需要
除以2
就能获取到。不用在原作者中过于复杂的转换。
使用SO_RCVBUF,设置sk->rcvbuf= 0x20000+fd, 通过
sk->rcvbuf
值可以识别其所属的fd。
〔4〕 打开
nr_memfds
个匿名共享文件(
memfd_create()
),分配物理页(
fallocate()
),这一步为文件分配
物理地址
。这里的物理地址不是顺序的,这一步很重要。
〔5〕 接着为文件映射
虚拟内存
,在固定地址处映射 65000 个连续的虚拟页(绑定该匿名文件),但是对应的物理页只有1个;并向
io_uring
注册该缓冲区。
〔6〕 越界读,定位到sock位置,泄露堆地址,内核基地址,然后伪造
subprocess_info
篡改
sock.__sk_common.skc_prot
为
CALL_USERMODEHELPER_EXEC
。
作者脏牛EXP
本质就是篡改
filp->f_mode
为可写,然后篡改
/etc/passwd
。
〔1〕 初始化:绑定CPU,注册io_uring,设置最大可打开文件数 (把rlim_cur设置为rlim_max),
nr_memfds
—— 映射漏洞物理页的文件最大打开数量。
nr_files
最大打开
file
数量。
〔2〕 创建
receiver_fd
,映射
receiver_buffer
内存(
mmap()
),用于存放数据(越界读取的数据和伪造的数据);
〔3〕 打开
nr_files
个
/etc/passwd
,因为通过
O_RDONLY
标识符打开,
f_mode
固定为
0x484a801d
。
〔4〕 接着为文件映射
虚拟内存
,在固定地址处映射 65000 个连续的虚拟页(绑定该匿名文件),但是对应的物理页只有1个;并向
io_uring
注册该缓冲区。
nr_pages
来源于用户设置的
iov.len/page_size
pages
里面就只有一个地址,所以很容易就绕过了之前说的判断
〔5〕 通过固定的
f_flags+f_mode == 0x484a801d00008000
定位到文件处,修改
f_mode
。
〔6〕因为无法知道文件描述符,所以暴力对所有
/etc/passwd
进行写操作,通过返回值判断是否写入成功,但是实测非常稳定,只要有这个漏洞就能提权。
0
人收藏
0
人喜欢
转载
分享
0
条评论
某人
表情
可输入
255
字
评论
发布投稿
热门文章
1
2025ISCC练武区域赛和决赛pwn以及擂台pwn合集
2
通过Elastic EDR看smbexec并进行二次开发Bypass
3
php代码审计篇 - 信呼OA 前台注入分析一
4
D3CTF-d3kshrm(预期&非预期)题解
5
Tomcat解析XML引入的新颖webshell构造方式
近期热点
一周
月份
季度
1
2025ISCC练武区域赛和决赛pwn以及擂台pwn合集
2
通过Elastic EDR看smbexec并进行二次开发Bypass
3
php代码审计篇 - 信呼OA 前台注入分析一
4
D3CTF-d3kshrm(预期&非预期)题解
5
Tomcat解析XML引入的新颖webshell构造方式
暂无相关信息
暂无相关信息
优秀作者
1
T0daySeeker
贡献值:28700
2
一天
贡献值:19800
3
1674701160110592
贡献值:18000
4
1174735059082055
贡献值:15000
5
Yale
贡献值:14000
6
LeeH
贡献值:10000
7
MeteorKai
贡献值:9000
8
姓*户
贡献值:8600
9
熊猫正正
贡献值:8000
10
lufei
贡献值:8000
目录
CVE-2023-2598 内核提权详细分析
漏洞简介
环境搭建
漏洞原理
folio
漏洞分析
io_sqe_buffers_register
io_sqe_buffer_register
网传EXP复现
作者脏牛EXP
转载
标题
作者:
你好
http://www.a.com/asdsabdas
文章
转载
自
复制到剪贴板